如何在 javascript 的数组中保留具有特定唯一属性的对象?

How to retain objects with a specific unique attribute in an array in javascript?

我有一个这样的数组:

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},
    ]

并且我想保留具有唯一 scaleId 的对象。因此,对于上面的示例,输出会像(如果 scaleId 重复,则可以保留任何随机对象):

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

我已经在我的应用程序中使用了下划线库,所以我可以接受使用下划线的实现。我想出了一个解决方案,但它没有按预期工作。所以,任何帮助都会很棒。

使用 reduce 并在回调内部检查累加器对象中是否存在具有相同 scaleId 的键。如果是这样,则将值添加到该键。最后使用 Object.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
  }
]

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

console.log(Object.values(data))

Maps 和 Sets 通常是保持唯一性的适当结构。这是一个简单的函数,它使用 Map 来维护给定 属性 名称的单个唯一值:

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)
)
.as-console-wrapper {min-height: 100% !important; top: 0}

此版本保留最后一个匹配值。如果你想要第一个匹配的,那只会稍微复杂一些。

您可以这样做(如果您使用的是 ES6/ES2015 或更高版本) 首先使用 Set 过滤唯一的 scaleIds 并使用 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)

您还可以使用Array.prototype.reduceRight()来简化聚合逻辑:

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);

或者构造一个Map from key-value pairs generated using 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 = Array.from(
  new Map(
    myarray.map(
      val => [val.scaleId, val]
    ).reverse()
  ).values()
).reverse(); // optional if order of output matters to you

console.log(myarray);

我们在传递给构造函数的数组上使用 Array.prototype.reverse() 以确保插入顺序允许较早的值优先于较晚的值。