webentwicklung-frage-antwort-db.com.de

Array von Objekten nach Eigenschaft mit Lodash zusammenführen

Ich habe zwei Arrays von Objekten, die E-Mail-Adressen darstellen, die eine Bezeichnung und einen Wert haben:

var original = [
  {
    label: 'private',
    value: '[email protected]'
  },
  {
    label: 'work',
    value: '[email protected]'
  }
];

var update = [
  {
    label: 'private',
    value: '[email protected]'
  },
  {
    label: 'school',
    value: '[email protected]'
  }
];

Jetzt möchte ich die beiden Arrays mit dem Feld label vergleichen und zusammenführen, so dass das Ergebnis so aussehen würde:

var result = [
  {
    label: 'private',
    value: '[email protected]'
  },
  {
    label: 'work',
    value: '[email protected]'
  },
  {
    label: 'school',
    value: '[email protected]'
  }
]

Wie kann ich das tun, z. mit lodash ?

32
benjiman

_.unionBy() :
Diese Methode ist wie _.union, außer dass sie Iteratee akzeptiert, der für jedes Element jedes Arrays aufgerufen wird, um das Kriterium zu generieren, nach dem die Eindeutigkeit berechnet wird. Ergebniswerte werden aus dem ersten Array ausgewählt, in dem der Wert vorkommt.

var original = [
  { label: 'private', value: '[email protected]' },
  { label: 'work', value: '[email protected]' }
];

var update = [
  { label: 'private', value: '[email protected]' },
  { label: 'school', value: '[email protected]' }
];

var result = _.unionBy(update, original, "label");

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

64
Andreas

Konvertieren Sie die Listen in Objekte, die mit label erstellt wurden, führen Sie sie mit _.assign zusammen und konvertieren Sie sie zurück in ein Array. Die Reihenfolge der Elemente in den meisten Browsern bleibt sogar erhalten.

var original = [
  {
    label: 'private',
    value: '[email protected]'
  },
  {
    label: 'work',
    value: '[email protected]'
  }
];

var update = [
  {
    label: 'private',
    value: '[email protected]'
  },
  {
    label: 'school',
    value: '[email protected]'
  }
];

console.log(
  _.map(
    _.assign(
      _.mapKeys(original, v => v.label),
      _.mapKeys(update, v => v.label)
    )
  )
);


// or remove more duplicated code using spread

console.log(
  _.map(
    _.assign(
      ...[original, update].map(
        coll => _.mapKeys(coll, v => v.label)
      )
    )
  )
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.js"></script>

4
Tamas Hegedus

Vielleicht ein bisschen spät, aber alle Lösungen, die ich gesehen habe, fügen beide Arrays nicht korrekt zusammen. Sie verwenden eines der Arrays zum Looping und überschüssige Elemente im zweiten Array werden nicht hinzugefügt. .

Der richtige Weg ist, beide Arrays zu sortieren und innerhalb beider Arrays vorwärts zu bewegen, die Übereinstimmungselemente zusammenzuführen und die fehlenden Elemente aus beiden Arrays hinzuzufügen . Die vollständige Lösung finden Sie unten. Dies erfordert auch O (n + m), was das Beste ist, das Sie erhalten können (ohne den Rechenaufwand für die Sortierung selbst). In meinem Code habe ich die Daten bereits aus der Datenbank sortiert.

function mergeObjectsBasedOnKey(array1, array2, compareFn, mergeFn, alreadySorted) {
  var array1Index = 0;
  var array2Index = 0;

  const merged = [];

  if (!alreadySorted) {
    array1.sort(compareFn);
    array2.sort(compareFn);
  }

  while (array1Index < array1.length && array2Index < array2.length) {
    var comparedValue = compareFn(array1[array1Index], array2[array2Index]);
    if (comparedValue === 0) {
      merged.Push(mergeFn(array1[array1Index], array2[array2Index]));
      array1Index++;
      array2Index++;
    } else if (comparedValue < 0) {
      merged.Push(mergeFn(array1[array1Index]));
      array1Index++;
    } else {
      merged.Push(mergeFn(array2[array2Index]));
      array2Index++;
    }
  }
  while (array1Index < array1.length) {
    merged.Push(mergeFn(array1[array1Index]));
    array1Index++;
  }
  while (array2Index < array2.length) {
    merged.Push(mergeFn(array2[array2Index]));
    array2Index++;
  }
  return merged;
}


const array1 = [{
    "id": 10,
    isArray1: true
  },
  {
    "id": 11,
    isArray1: true
  },
  {
    "id": 12,
    isArray1: true
  },
];
const array2 = [{
    "id": 8,
    isArray2: true
  },
  {
    "id": 11,
    isArray2: true
  },
  {
    "id": 15,
    isArray2: true
  },
];

const result = mergeObjectsBasedOnKey(array1, array2, function(a, b) {
  return a.id - b.id;
}, function(a, b) {
  if (b) {
    return _.merge(a, b);
  }
  return _.merge(a, {
    isArray1: true,
    isArray2: true
  });
});

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Und die Ergebnisse wären:

[ { id: 8, isArray2: true, isArray1: true },
  { id: 10, isArray1: true, isArray2: true },
  { id: 11, isArray1: true, isArray2: true },
  { id: 12, isArray1: true, isArray2: true },
  { id: 15, isArray2: true, isArray1: true } ]
2
Ralph

Falls Sie lodash 3.x verwenden, wenn _.unionBy () nicht vorhanden war, können Sie _.union() und _.uniq() kombinieren, um dasselbe Ergebnis zu erhalten.

var original = [
  { label: 'private', value: '[email protected]' },
  { label: 'work', value: '[email protected]' }
];

var update = [
  { label: 'private', value: '[email protected]' },
  { label: 'school', value: '[email protected]' }
];

var result = _.uniq(_.union(update, original), "label"); 

console.log(result);
1
Manish Kumar

Ich weiß, es ist nicht das, wonach gefragt wurde, aber nur für den Fall, dass jemand auf dieser Seite gestolpert ist, wie Sie dies in Ramda tun:

var original = [
  { label: 'private', value: '[email protected]' },
  { label: 'work', value: '[email protected]' }
];

var updated = [
  { label: 'private', value: '[email protected]' },
  { label: 'school', value: '[email protected]' }
];

unionWith(eqBy(prop('label')), updated, original);
0
Revanth Kumar

Hier können Sie zwei Objekte mit Lodash zusammenführen:

let a = [{
    content: 'aaa',
    name: 'bbb2'
  },
  {
    content: 'aad',
    name: 'ccd'
  }
];

let b = [{
    content: 'aaa',
    name: 'bbb'
  },
  {
    content: 'aad1',
    name: 'ccd1'
  }
];

let c = [...a, ...b];

let d = _.uniq(c, function(data) {
  return data.content;
})

console.log(d);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

0
jain77