2
votes

Filtrer les objets uniques dans le tableau en fonction de la condition d'horodatage

J'ai le tableau suivant:

arr = arr.filter((e, index, self) =>
    index === self.findIndex((t) => (
        t.id === intent.id && t.lastUpdate > e.lastUpdate
    ))
)

J'ai besoin de filtrer le tableau en fonction du même ID, mais aussi de vérifier l'horodatage "lastUpdate" et de ne conserver que les nouvelles entrées. Le résultat devrait être:

[
    {"id": 456, "lastUpdate": 1545269320},
    {"id": 123, "lastUpdate": 1552184795}
]

J'ai essayé ce qui suit:

let arr = [
    {"id": 123, "lastUpdate": 1543229793},
    {"id": 456, "lastUpdate": 1545269320},
    {"id": 123, "lastUpdate": 1552184795}
]

Cependant, cela filtre tout pour moi et le le tableau résultant est vide. Je pense que quelque chose ne va pas avec la dernière partie de && t.lastUpdate> e.lastUpdate ci-dessus.

Merci beaucoup pour vos conseils!


0 commentaires

4 Réponses :


3
votes

Vous pouvez y parvenir en recherchant les éléments qui n'ont pas d'élément2 où la mise à jour a été ultérieure

   arr.filter(item => 
                 { return !arr.some(item2 => 
                  item.id === item2.id && item.lastUpdate < item2.lastUpdate)
            });

Ce que fait ce code est:

Pour chaque élément dans le tableau, il regarde si dans le tableau il y a un élément avec le même identifiant où le lastUpdate est supérieur au sien. S'il y en a un, il renvoie true (Array.some renvoie un booléen). Nous annulons cette valeur et l'utilisons pour filtrer.


1 commentaires

Belle idée de combiner des négatifs "arr.some" et "arr.filter"! Fonctionne en effet, merci pour la réponse rapide!



0
votes

Vous pouvez le faire étape par étape en convertissant en un ensemble, en triant puis en obtenant le premier élément pour chaque identifiant:

let arr = [
    {"id": 123, "lastUpdate": 1543229793},
    {"id": 456, "lastUpdate": 1545269320},
    {"id": 123, "lastUpdate": 1552184795}
]

// Get the ids by making a set of ids and then converting to array
let ids = [ ...new Set(arr.map((e) => e.id)) ];

// Sort the original by lastUpdate descending
arr.sort((a, b) => b.lastUpdate - a.lastUpdate);

// Get array of first item from arr by id
let res = ids.map(id => arr.find((e) => e.id == id));

console.log(res);


0 commentaires

6
votes

Salut, si vous cherchez une solution performante vous pouvez utiliser un objet :)

let arr = [{"id": 123,"lastUpdate": 1543229793},
{"id": 456,"lastUpdate": 1545269320},
{"id": 123, "lastUpdate": 1552184795}];

let newArr = {}
arr.forEach(el => {
  if(!newArr[el.id] || newArr[el.id].lastUpdate < el.lastUpdate){
      newArr[el.id] = el
  }
})

console.log(Object.values(newArr));


1 commentaires

L'ajout de ceci comme réponse acceptée, en raison de meilleures performances.



0
votes

L'approche de Silvio emballée en code réutilisable, réduit le problème de l'OP à par exemple quelque chose comme ça ...

.as-console-wrapper { max-height: 100%!important; top: 0; }
function collectUniqueItemByIdWithMostRecentUpdate (collector, item, idx, arr) {
    const store = collector.store;
    const storedItem = store[item.id];

    if (!storedItem || (storedItem.lastUpdate < item.lastUpdate)) {
        store[item.id] = item;
    }
    if (idx >= (arr.length - 1)) {
        collector.list = Object.values(store);
    }
    return collector;
}

let arr = [
    {"id": 123, "lastUpdate": 1543229793},
    {"id": 456, "lastUpdate": 1555269320},
    {"id": 123, "lastUpdate": 1552184795},
    {"id": 456, "lastUpdate": 1545269320},
    {"id": 123, "lastUpdate": 1553229793}
];

console.log(arr.reduce(collectUniqueItemByIdWithMostRecentUpdate, {

    store: {},
    list: []

}).list);


0 commentaires