【问题标题】:How to remove all combination with the same element in subarray from array?如何从数组中删除子数组中具有相同元素的所有组合?
【发布时间】:2020-04-07 09:03:28
【问题描述】:

我有这个数组

[[1,2,3],[4,1,6],[1,3,2],[1,2,4],[3,1,2],[4,6,1],[9,9,9]]

并且我想要一个执行此操作的函数:

[[1,2,3],[4,1,6],[1,2,4],[9,9,9]].

此函数删除所有具有相同值的子数组。

我想过这样的过滤器

.filter(el => el.filter(value => array2.includes(value)))

但我不认为它会起作用。

PS:我使用 node.js

编辑:奇怪的是,您的许多答案都适用于该示例,但不适用于我的真实程序......事实上,我使用的是对象而不是数字。像这样:[[obj,obj,obj],[obj,obj,obj],[obj,obj,obj]]。但我不知道为什么它适用于数字而不是对象......

EDIT2:我现在给出一个最小的例子,这个对象:

注意实际数组可以有 20,000 个项目

  [
      [
        { name: 'Dofawa', item_type: 'Dofus', level: 6 },
        {
          name: 'Dofus Cawotte',
          item_type: 'Dofus',
          level: 6
        },
        {
          name: 'Dofus Kaliptus',
          item_type: 'Dofus',
          level: 6
        }
      ],
      [
        { name: 'Dofawa', item_type: 'Dofus', level: 6 },
        {
          name: 'Dofus Emeraude',
          item_type: 'Dofus',
          level: 6
        },
        {
          name: 'Dofus Ocre',
          item_type: 'Dofus',
          level: 6
        }
      ],
      [
        { name: 'Dofawa', item_type: 'Dofus', level: 6 },
        {
          name: 'Dofus Kaliptus',
          item_type: 'Dofus',
          level: 6
        },
        {
          name: 'Dofus Cawotte',
          item_type: 'Dofus',
          level: 6
        }
      ],
      [
        {
          name: 'Dofus Cawotte',
          item_type: 'Dofus',
          level: 6
        },
        {
          name: 'Dofus Kaliptus',
          item_type: 'Dofus',
          level: 6
        },
        { name: 'Dofawa', item_type: 'Dofus', level: 6 }
      ]
  ]

应该给这个对象:

  [
      [
        { name: 'Dofawa', item_type: 'Dofus', level: 6 },
        {
          name: 'Dofus Cawotte',
          item_type: 'Dofus',
          level: 6
        },
        {
          name: 'Dofus Kaliptus',
          item_type: 'Dofus',
          level: 6
        }
      ],
      [
        { name: 'Dofawa', item_type: 'Dofus', level: 6 },
        {
          name: 'Dofus Emeraude',
          item_type: 'Dofus',
          level: 6
        },
        {
          name: 'Dofus Ocre',
          item_type: 'Dofus',
          level: 6
        }
      ]
  ]

【问题讨论】:

  • 您的对象不起作用,因为它们的 toStrings 都将是 [object][object] 而不是“1,2,3”。这表明了提供minimal reproducible example 的重要性。您也许可以使用 JSON.stringify 而不是 sort
  • @mplungjan 并不是我在我的帖子中发布了编辑。
  • 忽略它,“dofus ocre”的效果总是一样的,我将删除这个属性以便清晰易懂
  • 从另一个评论“可以有 20000 个项目”。请阅读How to Ask

标签: javascript arrays node.js


【解决方案1】:

通过使用 aaray 和对象并且此对象具有相同的键顺序,您可以将每个对象作为单个 JSON 字符串并对 JSON 数组进行排序并将此字符串连接到单个字符串并将此字符串作为值用于检查 Set 的唯一性。

const
    normalize = v => v.map(o => JSON.stringify(o)).sort().join('|'),
    filterWithSet = s => v => (n => !s.has(n) && s.add(n))(normalize(v)),
    data = [[{ name: 'Dofawa', item_type: 'Dofus', level: 6 }, { name: 'Dofus Cawotte', item_type: 'Dofus', level: 6 }, { name: 'Dofus Kaliptus', item_type: 'Dofus', level: 6 }], [{ name: 'Dofawa', item_type: 'Dofus', level: 6 }, { name: 'Dofus Emeraude', item_type: 'Dofus', level: 6 }, { name: 'Dofus Ocre', item_type: 'Dofus', level: 6 }], [{ name: 'Dofawa', item_type: 'Dofus', level: 6 }, { name: 'Dofus Kaliptus', item_type: 'Dofus', level: 6 }, { name: 'Dofus Cawotte', item_type: 'Dofus', level: 6 }], [{ name: 'Dofus Cawotte', item_type: 'Dofus', level: 6 }, { name: 'Dofus Kaliptus', item_type: 'Dofus', level: 6 }, { name: 'Dofawa', item_type: 'Dofus', level: 6 }]],
    unique = data.filter(filterWithSet(new Set));

console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 更像这样:[[{a: "zaza", b:"zizi", c:"zozo"},{a: "zaza1", b:"zizi1", c:" zozo1"},{a:"zaza2", b:"zizi2", c:"zozo2"}],[{a:"zaza1", b:"zizi1", c:"zozo1"},{a:" zaza", b:"zizi", c:"zozo"},{a:"zaza2", b:"zizi2", c:"zozo2"}],[{a:"zaza", b:"zizi" , c:"zozo"},{a:"zaza1", b:"zizi1", c:"zozo1"},{a:"sbeve2", b:"sbive2", c:"sbove2"}],[ {a:"zaza", b:"zizi", c:"zozo"},{a:"sbeve2", b:"sbive2", c:"sbove2"},{a:"zaza1", b:" zizi1", c:"zozo1"}]]
  • 对象的属性是否总是相同的顺序?
  • 什么顺序?外部数组中的对象?
  • 主数组中的每个子数组都有这样的对象组合:[ { name: 'Dofawa', item_type: 'Dofus', level: 6 }, { name: 'Dofus Cawotte', item_type: 'Dofus', level: 6 }, { name: 'Dofus Kaliptus', item_type: 'Dofus', level: 6 } ] 每个对象具有相同数量的属性和相同的属性顺序。看主帖上的例子
【解决方案2】:

使用reduce() 函数并使用JSON.stringify() 将当前排序的数组与已添加到累加器的数组进行比较。

const arr = [[1,2,3],[4,1,6],[1,3,2],[1,2,4],[3,1,2],[4,6,1],[9,9,9]];

const res = arr.reduce((acc,cur) => {
    let match = false;
    acc.forEach(el => {
       if(JSON.stringify(cur.concat().sort()) === JSON.stringify(el.concat().sort())){
          match = true;
       }
    });

    return match ? acc : acc.concat([cur]);
},[]);

console.log(res);

【讨论】:

  • 请注意,您的结果与 OP 预期的结果不同
  • el.sort() 正在更改 arr 变量中的原始子数组,我也发生了同样的情况。
  • 您的回答似乎不错,但对于我真正的程序,它似乎非常繁重,我等待了 20 多秒,但它没有继续工作,我使用了大约 20000 个元素的数组...
【解决方案3】:

从技术上讲,它可以通过创建一个哈希表来解决,在该哈希表中,您只将唯一数组作为键添加到一个空的 {} 对象中。可以通过首先对子数组进行排序并添加为对象的键来创建唯一值。最后,您可以从对象中取出带有Object.values() 的值。

基于这个想法,我想这对你有用:

const array = [[1,2,3],[4,1,6],[1,3,2],[1,2,4],[3,1,2],[4,6,1],[9,9,9]];
const result = {};
array.forEach(a => {
  const t = Array.from(a).sort((a,b) => a - b);
  if (!result[t]) result[t] = a;
});

console.log(Object.values(result));

来自Object.values() 文档:

Object.values() 方法返回给定对象自己的可枚举属性值的数组,其顺序与 for...in 循环提供的顺序相同(不同之处在于 for-in 循环枚举原型链)。

我希望这会有所帮助!

【讨论】:

  • 请注意您的结果与 OP 预期的结果不同
  • @mickl 对,sort 做到了!刚刚更正,我已经用Array.from() 克隆了成功的子数组。谢谢,好收获!
  • 与数字完美搭配,但不适用于我的示例,我忘记添加了。现在它在主帖上。
【解决方案4】:

您可以使用Array.reduce 将排序数组作为键来构建字典,然后使用Object.values 检索非重复数组:

let input = [[1,2,3],[4,1,6],[1,3,2],[1,2,4],[3,1,2],[4,6,1],[9,9,9]]

let dict = input.reduce((state, current) => {
   let key = [...current].sort((a,b) => a - b).toString(); 
   if(!state[key]){
      state[key] = current;
   }
   
   return state;

}, {});

let result = Object.values(dict);

console.log(result);

【讨论】:

    猜你喜欢
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 2016-12-08
    相关资源
    最近更新 更多