【问题标题】:Find common elements within dynamic array's object elements Javascript在动态数组对象元素Javascript中查找公共元素
【发布时间】:2017-06-29 11:01:41
【问题描述】:

有很多关于这个主题的问题,但我找不到直接解决我遇到的问题的答案。

这是一个:Find common elements in 1 array using Javascript

第一个区别是我有一个不同类型的数组,它的元素是对象,键值对,其中键是字符串,值是整数数组。

第二个区别是数组是动态的,这意味着有时它可能有零个元素,有时它可能有3个对象元素。

我正在分享下面的示例数组:

const array = [
  {"key1":[1,2,3]},
  {"key2":[2,3,4]},
  {"key3":[2,5,6]},
];

第三个区别是元素的顺序很重要,因此最终结果应该输出所有后续数组中存在的第一个元素的值。

结果应该是:

const result = [2];

因为 2 是这三个元素中唯一的公共整数。

如前所述,数组有时可能只有 1 个或 2 个元素,或者没有元素,应该考虑这些情况。

编辑 1:在 cmets 数组的值是唯一的

【问题讨论】:

  • 每个对象中有多个键还是只有一个,为什么?
  • 您的样本数组是您将使用的数据类型的一个很好的例子吗?
  • @Jonasw 每个对象中只有一个键,原因是我正在使用多个下拉列表,其中每个选项值对应于数组值。选择那些下拉目时,我必须找到值的交点。希望我能回答你的问题。
  • @evolutionxbox 是的,这是一个很好的例子,请阅读上面的评论以更好地了解情况
  • @bakhtiiar muzakparov 很好,但动态键总是一个非常非常糟糕的主意(难以使用,难以为解析器优化)。因此可能会将您的结构更改为 {id:"key1", values:[1,2,3]}

标签: javascript arrays ecmascript-6


【解决方案1】:

由于一个值​​只能在数组中出现一次,您可以连接数组,计算出现次数,过滤掉不等于原始数组长度的数组。

const findRecuring = (array) =>
  [...
    [].concat(...array.map((o) => Object.values(o)[0])) // combine to one array
   .reduce((m, v) => m.set(v, (m.get(v) || 0) + 1), new Map()) // count the appearance of all values in a map
 ] // convert the map to array of key/value pairs
 .filter(([, v]) => v === array.length) // filter those that don't appear enough times
 .map(([k]) => k); // extract just the keys

/** Test cases **/
console.log('Several:', findRecuring([
  {"key1":[6,1,2,3,8]},
  {"key2":[2,6,3,4,8]},
  {"key3":[2,5,6,8]},
]).join());

console.log('None: ', findRecuring([
  {"key1":[9,0,11]},
  {"key2":[2,6,3,4,8]},
  {"key3":[2,5,6,8]},
]).join());

【讨论】:

  • 将您标记为优雅且解释清楚的注释代码的答案。
【解决方案2】:
const array = [
  {"key1":[1,2,3]},
  {"key2":[2,3,4]},
  {"key3":[2,5,6]},
];

您可以迭代并存储每个值在数组中出现的频率:

var common=new Map();
array.forEach(function(obj){
 //var values=new Set(Object.values(obj)[0]);//make unique values out of array
 var values=Object.values(obj)[0];//no need for uniqueness as OP states that they are already unique..
 values.forEach(function(val){
     common.set(val,(common.get(val)||0)+1);
 });
});

现在您已经获得了一个包含所有元素及其在主数组中的外观的地图。所以现在你可以简单地比较一下:

var result=[];
common.forEach(function(appearance,el){
  if(appearance===array.length){
   result.push(el);
  }
});

http://jsbin.com/xuyogahija/edit?console

【讨论】:

    【解决方案3】:

    您可以在不使用不同键的情况下首先获取数组中的数组,然后查找每个元素是否在另一个数组中。

    let array = [{ key1: [1, 2, 3] }, { key2: [2, 3, 4] }, { key3: [2, 5, 6] }],
        result = array
            .map(o => o[Object.keys(o)[0]] || [])
            .reduce((a, b) => a.filter(c => b.includes(c)));
          
    console.log(result);

    【讨论】:

    • 虽然您的解决方案看起来非常优雅,但当根本没有元素时它会失败。我得到的错误: "Uncaught TypeError: Reduce of empty array with no initial value..." 。我想知道如何修改你的代码来解决这个问题。
    • Array.prototype.reduce() 旨在接受第二个参数,即初始值。在这种情况下,它将是.reduce((a, b) => a.filter(c => b.includes(c)), []);。如果您处理的数组(或变量)为空/空,则返回此初始值。
    • @Ksyqo,那么结果总是空的。
    • @BakhtiiarMuzakparov,如果没有给出属性,你可以添加一个默认数组。
    • @Ksyqo 我现在得到的是空数组而不是 [2]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 1970-01-01
    相关资源
    最近更新 更多