1
votes

Comment conserver des objets avec un attribut unique spécifique dans un tableau en javascript?

J'ai un tableau comme celui-ci:

myarray = [
    {"scaleId":"001","currentWeight":0.200}
    {"scaleId":"002","currentWeight":0.300},
    {"scaleId":"003","currentWeight":0.340},
    ]

et je veux conserver les objets qui ont un scaleId unique. Donc, pour l'exemple ci-dessus, la sortie voudrait (tout objet aléatoire peut être conservé si le scaleId est dupliqué):

var myarray = [
    {"scaleId":"001","currentWeight":0.200}
    {"scaleId":"002","currentWeight":0.300},
    {"scaleId":"001","currentWeight":0.255},
    {"scaleId":"002","currentWeight":0.000},
    {"scaleId":"003","currentWeight":0.340},
    ]

J'utilise déjà la bibliothèque de soulignement dans mon application , donc je suis d'accord avec l'implémentation en utilisant un soulignement. J'avais trouvé une solution mais cela ne fonctionne pas comme prévu. Donc, toute aide sera formidable.


0 commentaires

4 Réponses :


0
votes

Utilisez réduire et vérifiez à l'intérieur du rappel si dans l'objet accumulateur il y a une clé avec le même scaleId. Si tel est le cas, ajoutez la valeur à cette clé. Enfin, utilisez Object.values ​​ pour créer un tableau de valeurs

var myarray = [{
    "scaleId": "001",
    "currentWeight": 0.200
  },
  {
    "scaleId": "002",
    "currentWeight": 0.300
  },
  {
    "scaleId": "001",
    "currentWeight": 0.255
  },
  {
    "scaleId": "002",
    "currentWeight": 0.000
  },
  {
    "scaleId": "003",
    "currentWeight": 0.340
  }
]

let data = myarray.reduce((acc, curr) => {
  if (!acc[curr.scaleId]) {
    acc[curr.scaleId] = curr
  }
  return acc;
}, {});

console.log(Object.values(data))


0 commentaires

1
votes

Les

Cartes et Ensembles sont souvent les structures appropriées pour maintenir l'unicité. Voici une fonction simple qui utilise une Map pour conserver une seule valeur unique en fonction d'un nom de propriété:

.as-console-wrapper {min-height: 100% !important; top: 0}
const uniqByProp = (prop) => (xs) =>
  [... new Map (xs .map ((x) => [x [prop], x])) .values ()]

var myarray = [{scaleId: "001", currentWeight: 0.200}, {scaleId: "002", currentWeight: 0.300}, {scaleId: "001", currentWeight: 0.255}, {scaleId: "002", currentWeight: 0.000}, {scaleId: "003", currentWeight: 0.340}]

console .log (
  uniqByProp ('scaleId') (myarray)
)

Cette version conserve la dernière valeur correspondante. Si vous voulez le premier correspondant, ce ne serait que légèrement plus complexe.


4 commentaires

Par intérêt, y a-t-il une ressource que je peux lire sur le style de code particulier que vous utilisez? Je ne vois pas cela souvent utilisé, même si je suis conscient que c'est courant parmi ceux qui favorisent la PF.


@PatrickRoberts: Je ne sais pas ce qui vous intéresse dans mon style. Je suis fan de FP, donc je suppose que je correspond à un stéréotype! Je préfère les fonctions curry . Je préfère les fonctions simples à usage unique mais idéalement génériques, mais cela me semble logique. Je suis prêt à écrire des lignes assez larges, mais j'aime certains espaces inhabituels (par exemple xs .map (...) plutôt que xs.map (...) , mais c'est une particularité mineure plus qu'un style cohérent. Ou est-ce autre chose?


C'était l'utilisation des espaces blancs que je notais particulièrement. Il n'y a pas de norme pour cela alors? J'ai vu cela utilisé de manière assez cohérente lorsque les personnes orientées FP écrivent du JavaScript.


@PatrickRoberts. Je ne connais aucun guide de style qui le suggère. Je l'ai emprunté et quelques autres idées de formatage à un autre utilisateur SO qui a depuis changé le style des espaces. Les messages de cet utilisateur contiennent une multitude de techniques utiles. Le formatage est clairement dérivé du formatage du langage de type LISP.



0
votes

Vous pouvez le faire de cette façon (si vous utilisez ES6 / ES2015 ou une version ultérieure) Utilisation de Set pour filtrer d'abord les scaleIds uniques et alimenter un nouveau tableau avec la méthode Array.find

var myarray = [
    {"scaleId":"001","currentWeight":0.200},
    {"scaleId":"002","currentWeight":0.300},
    {"scaleId":"001","currentWeight":0.255},
    {"scaleId":"002","currentWeight":0.000},
    {"scaleId":"003","currentWeight":0.340},
]

let scaleIds = [...new Set(myarray.map(item => item.scaleId))];
let filtered = []
scaleIds.forEach(scaleId => filtered.push(myarray.find(item => item.scaleId === scaleId)))

console.log(filtered)


0 commentaires

0
votes

Vous pouvez également utiliser Array.prototype.reduceRight () pour simplifier la logique d'agrégation:

let myarray = [
  { scaleId: '001', currentWeight: 0.2 },
  { scaleId: '002', currentWeight: 0.3 },
  { scaleId: '001', currentWeight: 0.255 },
  { scaleId: '002', currentWeight: 0 },
  { scaleId: '003', currentWeight: 0.34 }
];

myarray = Array.from(
  new Map(
    myarray.map(
      val => [val.scaleId, val]
    ).reverse()
  ).values()
).reverse(); // optional if order of output matters to you

console.log(myarray);

ou construisez un Mapper à partir de paires clé-valeur générées à l'aide de Array.prototype.map () :

let myarray = [
  { scaleId: '001', currentWeight: 0.2 },
  { scaleId: '002', currentWeight: 0.3 },
  { scaleId: '001', currentWeight: 0.255 },
  { scaleId: '002', currentWeight: 0 },
  { scaleId: '003', currentWeight: 0.34 }
];

myarray = Object.values(
  myarray.reduceRight(
    (acc, cur) => (acc[cur.scaleId] = cur, acc),
    {}
  )
).reverse(); // optional if order of output matters to you

console.log(myarray);

Nous utilisons Array.prototype.reverse () sur le tableau passé au constructeur pour s'assurer que l'ordre d'insertion permet aux valeurs antérieures de prendre le pas sur les valeurs ultérieures.


0 commentaires