У меня есть два массива, как это:
A=(vol-175a3b54 vol-382c477b vol-8c027acf vol-93d6fed0 vol-71600106 vol-79f7970e vol-e3d6a894 vol-d9d6a8ae vol-8dbbc2fa vol-98c2bbef vol-ae7ed9e3 vol-5540e618 vol-9e3bbed3 vol-993bbed4 vol-a83bbee5 vol-ff52deb2)
B=(vol-175a3b54 vol-e38d0c94 vol-2a19386a vol-b846c5cf vol-98c2bbef vol-7320102b vol-8f6226cc vol-27991850 vol-71600106 vol-615e1222)
Массивы не отсортированы и могут даже содержать дублированные элементы.
Я хотел бы сделать пересечение этих двух массивов и сохранить элементы в другом массиве. Как бы я это сделал?
Кроме того, как я могу получить список элементов, которые появляются в B и недоступны в A?
foo
два раза), нужно ли их дублировать в результате?Ответы:
comm(1)
это инструмент, который сравнивает два списка и может дать вам пересечение или разницу между двумя списками. Списки должны быть отсортированы, но этого легко достичь.Чтобы получить ваши массивы в отсортированный список, подходящий для
comm
:Это превратит массив A в отсортированный список. Сделайте то же самое для Б.
Чтобы использовать
comm
для возврата пересечения:-1 -2
говорит удалить записи, уникальные для file1 (A) и уникальные для file2 (B) - пересечение двух.Чтобы он вернул то, что находится в файле 2 (B), но не в файле 1 (А):
-1 -3
говорит удалить записи, уникальные для file1 и общие для обоих - оставляя только те, которые уникальны для file2.Чтобы ввести два конвейера
comm
, используйте функцию «Замена процесса»bash
:Чтобы захватить это в массиве:
Собираем все вместе:
источник
\n
.\n
это попробуйте:arr1=( one two three "four five\nsix\nseven" ); arr2=( ${arr1[@]:1} "four five\\nsix" ); n1=${#arr1[@]}; n2=${#arr2[@]}; arr=( ${arr1[@]/ /'-_-'} ${arr2[@]/ /'-_-'} ); arr=( $( echo "${arr[@]}"|tr '\t' '-t-'|tr '\n' '-n-'|tr '\r' '-r-' ) ); arr1=( ${arr[@]:0:${n1}} ); arr2=( ${arr[@]:${n1}:${n2}} ); unset arr; printf "%0.s-" {1..10}; printf '\n'; printf '{'; printf " \"%s\" " "${arr1[@]}"; printf '}\n'; printf "%0.s-" {1..10}; printf '\n'; printf '{'; printf " \"%s\" " "${arr2[@]}"; printf '}\n'; printf "%0.s-" {1..10}; printf '\n\n'; unset arr1; unset arr2
LC_ALL=C
. Вместо этого установитеLC_COLLATE=C
для того же увеличения производительности без других побочных эффектов. Чтобы получить правильные результаты, вам также необходимо установить такое же сопоставление,comm
которое использовалось дляsort
, например:unset LC_ALL; LC_COLLATE=C ; comm -12 <(printf '%s\n' "${A[@]}" | sort) <(printf '%s\n' "${B[@]}" | sort)
Вы можете получить все элементы, которые находятся как в A, так и в B, просматривая оба массива и сравнивая:
Вы можете получить все элементы в B, но не в A аналогичным образом:
источник
A
иB
, этоintersections
всегда то же самое до переназначения?Существует довольно элегантный и эффективный подход для этого, использующий
uniq
- но нам нужно будет исключить дубликаты из каждого массива, оставив только уникальные элементы. Если вы хотите сохранить дубликаты, есть только один способ «перебрать оба массива и сравнить».Предположим, у нас есть два массива:
Прежде всего, давайте преобразуем эти массивы в наборы. Мы сделаем это потому, что существует пересечение математических операций, которое известно как пересечение множеств, а множество - это совокупность отдельных объектов, отличных или уникальных . Если честно, я не знаю, что такое «пересечение», если мы говорим о списках или последовательностях. Хотя мы можем выбрать подпоследовательность из последовательности, но эта операция (выборка) имеет немного другое значение.
Итак, давайте преобразимся!
пересечения:
Если вы хотите сохранить элементы в другом массиве:
uniq -d
означает показывать только дубликаты (я думаю,uniq
это довольно быстро из-за его реализации: я думаю, что это делается с помощьюXOR
операции).Получить список элементов, которые появляются в
B
и не доступныA
, т.е.B\A
Или с сохранением в переменной:
Таким образом, сначала у нас есть пересечение
A
иB
(что является просто набором дубликатов между ними), скажем, что это такA/\B
, а затем мы использовали операцию инвертирования пересеченияB
иA/\B
(что является просто уникальными элементами), так что мы получаемB\A = ! (B /\ (A/\B))
.PS
uniq
был написан Ричардом М. Столлманом и Дэвидом Маккензи.источник
Игнорируя эффективность, вот подход:
источник
Мой чистый путь
Как содержать эти переменные только
vol-XXX
гдеXXX
это шестнадцатеричное число, есть быстрый способ с использованием Баш массивовЭто должно вывести:
В этом состоянии ваша среда bash содержит:
Чтобы вы могли:
Это сделает:
Но это численно! Если вы хотите оригинальный заказ, вы можете:
Таким образом, вы отображаете vols в том же порядке, что и submited:
или
для показа только в A :
или даже:
будет повторно печатать :
источник
Duplicate
линии бесполезны, их можно просто отбросить.