Estoy trabajando en un proyecto paralelo en el que comparo dos bases de datos diferentes y quiero encontrar los elementos comunes de los conjuntos de datos basados en el campo "id". Quiero saber si existe una solución óptima en lugar de usar dos bucles for anidados. ¿Hay alguna manera de hacerlo con un mapa hash? ¡Muchas gracias! A continuación se muestra el código de muestra con el que estoy trabajando.
ACTUALIZAR todas las identificaciones son únicas sin posibilidad de que haya un duplicado
// data set 1 const set1 = [ { id: "001", name: "bob", age: "50", location: "texas" }, { id: "002", name: "bill", age: "51", location: "texas" }, { id: "003", name: "ben", age: "52", location: "texas" }, { id: "004", name: "cam", age: "53", location: "texas" }, { id: "005", name: "max", age: "54", location: "texas" } ] // data set 2 const set2 = [ { id: "001", name: "bob" }, { id: "002", name: "bill" } ] // I want to create a function where I find the the common elements of the two lists based on id and put the common element of data set 1 into a list and return that list const findUnion(set1, set2) { // logic here, I know I can do a nested for loop but is there a more efficient way such as // using a hashmap? ( Map() object? ) } // desired output const output = [ { id: "001", name: "bob", age: "50", location: "texas" }, { id: "002", name: "bill", age: "51", location: "texas" } ]Puede usar Set s para una búsqueda eficiente:
const ids1 = new Set(set1.map(({id}) => id)); const ids2 = new Set(set2.map(({id}) => id)); const output = set1.filter(({id}) => ids1.has(id) && ids2.has(id)); console.log(output);Primero combinamos en una matriz larga. Luego agrupe por id usando el método de reduce . Cada grupo contiene el elemento y el recuento de apariciones. Finalmente, para cada uno de los grupos, devuelva solo aquellos con recuento de apariciones > 1.
Editar: algoritmo fijo ver código.
Edición 2: lo hizo más genérico para que el orden de los elementos no importe. Esto se logra extendiendo los duplicados en lugar de reemplazarlos.
function findUnion(set1, set2) { // first remove duplicates from each set // bonus: collect duplicates var duplicates; function dedup(set) { duplicates = [] return Object.values(set.reduce(function(agg, item) { var merged = item; if (agg[item.id]) { merged = { ...agg[item.id], ...item } duplicates.push(merged) } agg[item.id] = merged; return agg }, {})); } set1 = dedup(set1); set2 = dedup(set2); // then combine var combined = [...set1, ...set2] // then remove duplicates again, this time keep them dedup(combined) return duplicates; } // data set 1 const set1 = [{ id: "001", name: "bob", age: "50", location: "texas" }, { id: "002", name: "bill", age: "51", location: "texas" }, { id: "003", name: "ben", age: "52", location: "texas" }, { id: "004", name: "cam", age: "53", location: "texas" }, { id: "005", name: "max", age: "54", location: "texas" }, { id: "005", name: "max", age: "54", location: "texas" }, { id: "005", name: "max", age: "54", location: "texas" } ] // data set 2 const set2 = [{ id: "001", name: "bob" }, { id: "002", name: "bill" } ] // desired output const output = [{ id: "001", name: "bob", age: "50", location: "texas" }, { id: "002", name: "bill", age: "51", location: "texas" } ] console.log(findUnion(set1, set2))En primer lugar, busca la intersección , no la unión .
Como han dicho otros, podemos usar un Set para rastrear la singularidad. Esto nos da un tiempo de búsqueda cercano a O(1) y nos permite un algoritmo que se ejecuta en algo así como un O(m + n) donde m y n son los tamaños de su set s:
const intersection = (s1, s2, ids = new Set (s2 .map (x => x .id))) => s1 .filter (({id}) => ids .has (id)) const set1 = [{id: "001", name: "bob", age: "50", location: "texas"}, {id: "002", name: "bill", age: "51", location: "texas"}, {id: "003", name: "ben", age: "52", location: "texas"}, {id: "004", name: "cam", age: "53", location: "texas"}, {id: "005", name: "max", age: "54", location: "texas"}] const set2 = [{id: "001", name: "bob"}, {id: "002", name: "bill"}] console .log (intersection (set1, set2)) .as-console-wrapper {max-height: 100% !important; top: 0}