如何合并对象数组的所有数组以获得唯一值?

时间:2021-11-30 19:17:23

I've got some data like this:

我有一些这样的数据:

const items = [
  { _id: '1', reference: ['abc'] },
  { _id: '2', reference: ['def'] },
  { _id: '3', reference: ['abc'] }
]

The length of items is always different.

项目的长度总是不同的。

Now I need to get all unique reference strings in a single array. So the result should be

现在我需要在一个数组中获得所有唯一的引用字符串。所以结果应该是

['abc', 'def']

as 'abc' is a duplicate.

因为abc是一个复制品。

I tried to use a forEach() loop:

我尝试使用forEach()循环:

const references = []
items.forEach(i => {
  references.concat(i.reference)
})

console.log(references)

But references just gets an empty array result. Also with that I did not take care of duplicates...

但是引用只会得到一个空的数组结果。同时,我也没有处理重复的东西……


I would like to use an ES6 pattern. With that I know I could use something like this:

我想使用ES6模式。有了它,我知道我可以用这样的东西:

const array1 = ['abc']
const array2 = ['def']
const array3 = Array.from(new Set(array1.concat(array2)))

But how can I do this using a loop to get every reference array of each item object - even if I do not know how many objects are in the item array?

但是,如何使用循环来获取每个条目对象的每个引用数组—即使我不知道条目数组中有多少对象?

3 个解决方案

#1


2  

If you wanna do a functional style (map-reduce), you can do it like this

如果你想做一个函数样式(map-reduce),你可以这样做

const items = [
  { _id: '1', reference: ['abc'] },
  { _id: '2', reference: ['def'] },
  { _id: '3', reference: ['abc'] }
]

// extract references and put them into a single array
const references = 
  items
    .map(x => x.reference)
    .reduce((prev, cur) => prev.concat(cur))
    
// put them in a set to dedupe
const set = new Set(references)

console.log(references)
console.log([...set])

If you want to do fewer passes over the data, and also avoid the need for Set you could do.

如果您想减少对数据的传递,并且避免需要设置,您可以这样做。

const items = [
  { _id: '1', reference: ['abc'] },
  { _id: '2', reference: ['def'] },
  { _id: '3', reference: ['abc'] }
]

const result = Object.keys(items.reduce((obj, {reference}) => {
  for (const ref of reference) {
    obj[ref] = true
  }
  return obj;
}, {}))

console.log(result)

You can also trade expressiveness for performance with a fully imperative approach below.

您还可以使用下面的一种完全必要的方法来交换表现力和性能。

const items = [
  { _id: '1', reference: ['abc'] },
  { _id: '2', reference: ['def'] },
  { _id: '3', reference: ['abc'] }
];

const occ = {};
const references = [];
for (let i = 0; i < items.length; ++i) {
  const refs = items[i].reference;
  for (let j = 0; j < refs.length; ++j) {
    const ref = refs[j];
    if (occ[ref] == null) {
      references.push(ref);
      occ[ref] = true;
    }
  }
}

console.log(references)
  

#2


2  

If you want to use Sets, you can use Set.add, and spread syntax:

如果你想使用集合,你可以使用Set.add和spread语法:

const items = [
  { _id: '1', reference: ['abc'] },
  { _id: '2', reference: ['def'] },
  { _id: '3', reference: ['abc'] }
]

var references = new Set();
items.forEach(i => references.add(...i.reference))
console.log(Array.from(references))

#3


1  

This is similar to other solutions here, but creates a reusable function:

这与这里的其他解决方案类似,但创建了一个可重用的功能:

const uniqRefs = 
  items => [...items.reduce((s, i) => s.add(...i.reference), new Set())]


const items = [{"_id": "1", "reference": ["abc"]}, {"_id": "2", "reference": ["def"]}, {"_id": "3", "reference": ["abc"]}]
console.log(uniqRefs(items))

#1


2  

If you wanna do a functional style (map-reduce), you can do it like this

如果你想做一个函数样式(map-reduce),你可以这样做

const items = [
  { _id: '1', reference: ['abc'] },
  { _id: '2', reference: ['def'] },
  { _id: '3', reference: ['abc'] }
]

// extract references and put them into a single array
const references = 
  items
    .map(x => x.reference)
    .reduce((prev, cur) => prev.concat(cur))
    
// put them in a set to dedupe
const set = new Set(references)

console.log(references)
console.log([...set])

If you want to do fewer passes over the data, and also avoid the need for Set you could do.

如果您想减少对数据的传递,并且避免需要设置,您可以这样做。

const items = [
  { _id: '1', reference: ['abc'] },
  { _id: '2', reference: ['def'] },
  { _id: '3', reference: ['abc'] }
]

const result = Object.keys(items.reduce((obj, {reference}) => {
  for (const ref of reference) {
    obj[ref] = true
  }
  return obj;
}, {}))

console.log(result)

You can also trade expressiveness for performance with a fully imperative approach below.

您还可以使用下面的一种完全必要的方法来交换表现力和性能。

const items = [
  { _id: '1', reference: ['abc'] },
  { _id: '2', reference: ['def'] },
  { _id: '3', reference: ['abc'] }
];

const occ = {};
const references = [];
for (let i = 0; i < items.length; ++i) {
  const refs = items[i].reference;
  for (let j = 0; j < refs.length; ++j) {
    const ref = refs[j];
    if (occ[ref] == null) {
      references.push(ref);
      occ[ref] = true;
    }
  }
}

console.log(references)
  

#2


2  

If you want to use Sets, you can use Set.add, and spread syntax:

如果你想使用集合,你可以使用Set.add和spread语法:

const items = [
  { _id: '1', reference: ['abc'] },
  { _id: '2', reference: ['def'] },
  { _id: '3', reference: ['abc'] }
]

var references = new Set();
items.forEach(i => references.add(...i.reference))
console.log(Array.from(references))

#3


1  

This is similar to other solutions here, but creates a reusable function:

这与这里的其他解决方案类似,但创建了一个可重用的功能:

const uniqRefs = 
  items => [...items.reduce((s, i) => s.add(...i.reference), new Set())]


const items = [{"_id": "1", "reference": ["abc"]}, {"_id": "2", "reference": ["def"]}, {"_id": "3", "reference": ["abc"]}]
console.log(uniqRefs(items))