如何按 id 从对象数组中减少一个重复对象

How to reduce one of the duplicate object from array of objects by id

提问人:Almaz Kabiyev 提问时间:9/18/2023 最后编辑:PippoAlmaz Kabiyev 更新时间:9/19/2023 访问量:65

问:

我有一个对象数组:

const obj = [{
  id: 1,
  name: 'A'
}, {
  id: 1,
  name: 'A'
}, {
  id: 1,
  name: 'A'
}, {
  id: 2,
  name: 'A'
}, {
  id: 2,
  name: 'A'
}]

// this method returned me one object with id=1
const filter = obj.reduce((val, index) => {
  return index === val.findIndex(v => obj.id === v.id && obj.name === o.name)
})

当我按下按钮时,我想删除其中一个重复的对象。例如,我在 ID=1 的数组中有 3 个对象。我只想删除一个ID=1的对象,而不是两个。所以结果一定是这样的:

const obj = [{
  id: 1,
  name: 'A'
}, {
  id: 1,
  name: 'A'
}, {
  id: 2,
  name: 'A'
}, {
  id: 2,
  name: 'A'
}]
JavaScript 数组 对象 过滤器 减少

评论

1赞 Jaromanda X 9/18/2023
你的文本看起来像代码,你的代码看起来像文本....请编辑问题并使其可读
0赞 Rory McCrossan 9/18/2023
在提交问题之前,请花时间校对您的问题。坦率地说,在我编辑它之前,这是一个不可读的混乱。
0赞 CBroe 9/18/2023
Array.prototype.reduce() 上的 MDN:“在数组的所有元素上运行 reducer 的最终结果是单个值”——所以这可能不太适合你想要的。
0赞 mplungjan 9/18/2023
因此,如果 id=2 也有 3 个或更多条目,您是否也希望将其减少到最多 2 个条目?
0赞 Alexander Nenashev 9/18/2023
这就像您尝试将数据用作队列或堆栈一样。我建议重构您的数据

答:

0赞 Sash Sinha 9/18/2023 #1

您可以通过使用 Array.prototype 查找第一个对象的索引,然后使用 Array.prototype 来实现此目的。splice() 将其删除:id=1

const obj = [ { id: 1, name: 'A' }, { id: 1, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'A' }, { id: 2, name: 'A' } ];

const targetId = 1;
const indexToRemove = obj.findIndex(item => item.id === targetId);

if (indexToRemove !== -1) {
  obj.splice(indexToRemove, /*deleteCount=*/1);
}

console.log(obj);

评论

0赞 mplungjan 9/18/2023
可能有多个集合,并且不仅要对 id=1 的集合进行重复数据删除,以最多包含两个重复项
0赞 Sash Sinha 9/18/2023
#WeTakeThose #ThrivingInAmbiguity #PEP20Line20=FakeNews(面对模棱两可,拒绝猜测的诱惑。
0赞 mplungjan 9/18/2023 #2

下面是将接受任意数量的对象并最多保留两个重复项的代码

const filteredObj = arr.reduce((acc, curr) => {
  acc.count[curr.id] ??= 0; // conditional assignment
  acc.count[curr.id]++;
  // If the count is less than or equal to 2, add the object to the result array
  if (acc.count[curr.id] <= 2) {
    acc.result.push(curr);
  }
  return acc;
}, {
  count: {},
  result: []
}).result;

console.log(filteredObj);
<script>
const arr = [
  { id: 1, name: 'A' },
  { id: 1, name: 'A' },
  { id: 2, name: 'B' },
  { id: 2, name: 'B' },
  { id: 3, name: 'C' },
  { id: 1, name: 'A' },
  { id: 2, name: 'B' }
];
</script>

0赞 Ori Drori 9/19/2023 #3

创建一个 Map 来计算 .用于删除计数超过两次的所有项目:idArray.filter()id

const arr = [{"id":1,"name":"A"},{"id":1,"name":"A"},{"id":1,"name":"A"},{"id":2,"name":"A"},{"id":2,"name":"A"}]

const ids = new Map()

const result = arr.filter(o => {
  ids.set(o.id, (ids.get(o.id) ?? 0) + 1)
  
  return ids.get(o.id) <= 2
})

console.log(result)

0赞 dreamer 12/21/2023 #4

这可以通过用 .TrueSetid

import { TrueSet } from "@ut8pia/classifier/queue/TrueSet.js";
import { ORDER } from "@ut8pia/classifier/global.js";
import assert from "assert";

const 
    data = [{
        id: 1,
        name: 'A'
    }, {
        id: 1,
        name: 'A'
    }, {
        id: 1,
        name: 'A'
    }, {
        id: 2,
        name: 'A'
    }, {
        id: 2,
        name: 'A'
    }],

    expected = [{
        id: 1,
        name: 'A'
    }, {
        id: 1,
        name: 'A'
    }, {
        id: 2,
        name: 'A'
    }, {
        id: 2,
        name: 'A'
    }]

您需要做的就是将您的数据添加到 .TrueSet

const
    repr = item => item.id,
        
    set = TrueSet.of(repr, ORDER.ASCENDING)
        .letAll(data);

每个项目都存储在一个内部树结构中 - a ,其形式是键为 的节点路径。此树结构可通过 的属性访问。该方法在指定 处的所有子树中导航。每个返回的项目都提供一种方法,用于仅选择第一个项目。Classifier[item.id, item]set.classifierTrueSetClassifierviews(depth)depthviewqueueselect(max)max

set.classifier.views(1)
   .each(view => view.select(2));

就这样!现在,每个子树可以包含最大项目,因此,每个子树。TrueSet2item.id

您可以通过以下方式检查建议的解决方案的有效性:

assert.deepEqual(set.toArray(), expected)

值得注意的是,它本身就是简单项目的集合。该方法检索初始项,而不考虑它们在内部树结构中的表示形式。TrueSetset.toArray()