Tengo dos matrices como esta:
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)
Las matrices no están ordenadas y posiblemente podrían contener elementos duplicados.
Me gustaría hacer la intersección de estas dos matrices y almacenar los elementos en otra matriz. ¿Como podría hacerlo?
Además, ¿cómo obtendría la lista de elementos que aparecen en B y no están disponibles en A?
foo
dos veces), ¿los necesita duplicados en el resultado?Respuestas:
comm(1)
es una herramienta que compara dos listas y puede darle la intersección o diferencia entre dos listas. Las listas deben ordenarse, pero eso es fácil de lograr.Para obtener sus matrices en una lista ordenada adecuada para
comm
:Eso convertirá la matriz A en una lista ordenada. Haz lo mismo para B.
Para usar
comm
para devolver la intersección:-1 -2
dice que elimine las entradas exclusivas del archivo1 (A) y exclusivas del archivo2 (B): la intersección de las dos.Para que devuelva lo que está en el archivo 2 (B) pero no en el archivo 1 (A):
-1 -3
dice que elimine las entradas exclusivas de file1 y comunes a ambas, dejando solo aquellas exclusivas de file2.Para alimentar dos tuberías
comm
, utilice la función "Sustitución de proceso" debash
:Para capturar esto en una matriz:
Poniendolo todo junto:
fuente
\n
.\n
intente esto: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
. En cambio, establezcaLC_COLLATE=C
la misma ganancia de rendimiento sin otros efectos secundarios. Para obtener resultados correctos , también deberá establecer la misma clasificación para lacomm
que se utilizósort
, por ejemplo:unset LC_ALL; LC_COLLATE=C ; comm -12 <(printf '%s\n' "${A[@]}" | sort) <(printf '%s\n' "${B[@]}" | sort)
Puede obtener todos los elementos que están en A y B recorriendo ambas matrices y comparando:
Puede obtener todos los elementos en B pero no en A de manera similar:
fuente
A
yB
, ¿esintersections
siempre igual reordenar?Para hacerlo, hay un enfoque bastante elegante y eficiente,
uniq
pero tendremos que eliminar duplicados de cada matriz, dejando solo elementos únicos. Si desea guardar duplicados, solo hay una forma "recorriendo ambas matrices y comparando".Considere que tenemos dos matrices:
En primer lugar, transformemos estas matrices en conjuntos. Lo haremos porque no es matemática intersección operación que se conoce como la intersección de conjuntos, y el conjunto es una colección de distintos objetos, diferentes o únicas . Para ser honesto, no sé qué es "intersección" si hablamos de listas o secuencias. Aunque podemos seleccionar una subsecuencia de la secuencia, pero esta operación (selección) tiene un significado ligeramente diferente.
Entonces, ¡vamos a transformar!
Intersección:
Si desea almacenar los elementos en otra matriz:
uniq -d
significa mostrar solo duplicados (creo queuniq
es bastante rápido debido a su realización: supongo que se hace con laXOR
operación).Obtenga la lista de elementos que aparecen
B
y no están disponiblesA
, es decirB\A
O, al guardar en una variable:
Por lo tanto, al principio tenemos la intersección de
A
yB
(que es simplemente el conjunto de duplicados entre ellos), digamos que esA/\B
, y luego utilizamos la operación de la intersección invertida deB
yA/\B
(que simplemente son elementos únicos), por lo que obtenemosB\A = ! (B /\ (A/\B))
.PS
uniq
fue escrito por Richard M. Stallman y David MacKenzie.fuente
Ignorando la eficiencia, aquí hay un enfoque:
fuente
Mi puro estilo bash
Como estas variables contienen solo
vol-XXX
dondeXXX
hay un número hexadecimal, hay una forma rápida de usar matrices bashEsto debe generar:
En este estado, su entorno bash contiene:
Entonces podrías:
Esto rendirá:
¡Pero esto está ordenado numéricamente! Si desea un pedido original, podría:
Por lo tanto, muestra los vols en el mismo orden en que los envió:
o
para mostrar solo en A :
o incluso:
volverá a imprimir :
fuente
Duplicate
líneas son inútiles, simplemente se pueden descartar.