我正在尝试构建唯一的数组数组,这样每当我有新数组添加它时,只应添加它,如果它不存在于集合中
E.g。存储[1,1,2]
的所有唯一排列实际:[[1,1,2],[1,2,1],[1,1,2],[1,2,1],[2,1,1],[2,1,1]]
预期:[[1,1,2],[1,2,1],[2,1,1]]
我试过的方法:
uniqueArrComparer
中的每个值都是对该数组元素的唯一对象引用。function uniqueArrComparer(value, index, self) {
return self.indexOf(value) === index;
}
result.filter(uniqueArrComparer)
设置/映射:我认为我可以构建一个独特的数组,但它不起作用,因为Set内部使用严格相等比较器(===),它将考虑每个在这种情况下,数组是唯一的 We cannot customize object equality for JavaScript Set
将每个数组元素作为字符串存储在Set / Map / Array中,并构建一个唯一字符串数组。在最后使用唯一字符串数组构建数组数组。这种方法可行,但看起来不是有效的解决方案。
let result = new Set();
// Store [1,1,2] as "1,1,2"
result.add(permutation.toString());
return Array.from(result)
.map(function(permutationStr) {
return permutationStr
.split(",")
.map(function(value) {
return parseInt(value, 10);
});
});

这个问题比任何应用程序问题更像是一种学习练习。
答案 0 :(得分:7)
一种方法是将数组转换为JSON字符串,然后使用Set获取唯一值,然后再转换回来
var arr = [
[1, 1, 2],
[1, 2, 1],
[1, 1, 2],
[1, 2, 1],
[2, 1, 1],
[2, 1, 1]
];
let set = new Set(arr.map(JSON.stringify));
let arr2 = Array.from(set).map(JSON.parse);
console.log(arr2)

答案 1 :(得分:0)
为了解决每个数组作为唯一对象的问题,您可以对其进行字符串化,使其不再唯一,然后将其映射回数组。这应该可以解决问题:
var arr = [
[1, 1, 2],
[1, 2, 1],
[1, 1, 2],
[1, 2, 1],
[2, 1, 1],
[2, 1, 1]
];
var unique = arr.map(cur => JSON.stringify(cur))
.filter(function(curr, index, self) {
return self.indexOf(curr) == index;
})
.map(cur => JSON.parse(cur))
console.log(unique);
答案 2 :(得分:0)
您可以将Set
子类化,以通过存储对添加的对象调用JSON.stringify
的结果来更灵活地存储对象。
class ObjectSet extends Set{
add(elem){
return super.add(typeof elem === 'object' ? JSON.stringify(elem) : elem);
}
has(elem){
return super.has(typeof elem === 'object' ? JSON.stringify(elem) : elem);
}
}
let set = new ObjectSet([[1,1,2],[1,2,1],[1,1,2],[1,2,1],[2,1,1],[2,1,1]]);
console.log([...set]);
console.log([...set].map(JSON.parse));//get objects back
答案 3 :(得分:0)
如果可以使用库,请尝试lodash uniqWith。这将使用您选择的比较器(在您的情况下为等于)递归地找到数组或对象的组。
var arrayofarrays = [ [1,1,2], [1,2,1], [1,1,2], [1,2,1], [2,1,1], [2,1,1] ]
const uniqarray = _.uniqWith(arrayofarrays, _.isEqual);
console.log(uniqarray) //=> [[1, 1, 2], [1, 2, 1], [2, 1, 1]]
奖金:它也适用于对象数组
var objects = [{ 'x': 1, 'y': {b:1} }, { 'x': 1, 'y': {b:1} },
{ 'x': 2, 'y': {b:1} }, { 'x': 1, 'y': 2 } ];
const uniqarray = _.uniqWith(objects, _.isEqual);
console.log(uniqarray)
// => [{x: 1, y: {b: 1}}, {x: 2, y: {b: 1}}, {x: 1, y: 2}]
答案 4 :(得分:0)
我发现最快的方法是:
const points = [
[0,0],
[100,100],
[400,400],
[200,200],
[200,200],
[200,200],
[300,300],
[400,400],
]
const uniquePoints = Array.from(
new Map(points.map((p) => [p.join(), p])).values()
)
该线程中的所有方法都很快。然而,这个方法比 Set 方法更快,因为我们永远不需要将字符串化的数组转换回数组。
要查找唯一对象,请将 p.join()
替换为 JSON.stringify(p)
。
就我而言,上面显示的方法被证明是错误的策略,因为我只需要检查相同的相邻点。例如,上面使用的测试数组包含值 [400,400]
两次,但这些值不连续。上面显示的方法会删除第二个实例,而下面的代码会保留它。
points = points.filter(
(point, i) =>
i === 0 ||
!(points[i - 1][0] === point[0] && points[i - 1][1] === point[1])
)