【问题标题】:filter objects from array that have the same value at given key从数组中过滤在给定键处具有相同值的对象
【发布时间】:2017-09-01 10:45:18
【问题描述】:

假设我们有一个如下所示的数组:

[
    {
        id: 0,
        name: 'A'
    },
    {
        id: 1,
        name:'A'
    },
    {
        id: 2,
        name: 'C'
    },
    {
        id: 3,
        name: 'B'
    },
    {
        id: 4,
        name: 'B'
    }
]

我只想保留在 'name' 键处具有相同值的对象。所以输出看起来像这样:

[
    {
        id: 0,
        name: 'A'
    },
    {
        id: 1,
        name:'A'
    },
    {
        id: 3,
        name: 'B'
    },
    {
        id: 4,
        name: 'B'
    }
]

我想使用 lodash,但我没有看到任何适合这种情况的方法。

【问题讨论】:

  • 那么,你想保留其 'name' 值存在于多个对象中的对象,对吧?
  • 你能澄清一下吗?您只想保留 name 在数组中至少存在两次的对象?或者是成对的两个具有相同name的后续对象?
  • 我只想保留名称在数组中至少存在两次的对象
  • @sympi 啊,好吧,在这种情况下,Rajesh 的答案应该是解决方案,虽然它不使用 lodash。
  • 列表中每个元素的顺序是否重要?如果 id:1 (name: 'A)' 改为 id:5 会发生什么?

标签: javascript filter


【解决方案1】:

你可以试试这样的:

想法:

  • 遍历数据并创建一个名称列表及其计数。
  • 再次循环数据并过滤掉所有计数

var data = [{ id: 0, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'C' }, { id: 3, name: 'B' }, { id: 4, name: 'B' }];

var countList = data.reduce(function(p, c){
  p[c.name] = (p[c.name] || 0) + 1;
  return p;
}, {});

var result = data.filter(function(obj){
  return countList[obj.name] > 1;
});

console.log(result)

【讨论】:

  • 老实说,我确实检查了你的答案(不止一次),而且一如既往,它仍然让我头疼。会再读几遍。 ;-) 也将尝试在 1 个循环中执行此操作。感谢您指出。
  • 它适用于空数组,如果它稍后有效,那么它会获取一个带有更新的元素。 concat 过滤空元素。
【解决方案2】:

lodash 方法可能(或可能不会)更容易遵循以下步骤:

const originalArray = [{ id: 0, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'C' }, { id: 3, name: 'B' }, { id: 4, name: 'B' }];

const newArray =
      _(originalArray)
      	.groupBy('name') // when names are the same => same group.  this gets us an array of groups (arrays)
        .filter(group => group.length == 2) // keep only the groups with two items in them
        .flatten() // flatten array of arrays down to just one array
        .value();
        
console.log(newArray)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>

【讨论】:

    【解决方案3】:

    使用 array.filter 和 array.some 的更短的解决方案:

    var data = [ { ... }, ... ];  // Your array
    var newData = data.filter((elt, eltIndex) => data.some((sameNameElt, sameNameEltIndex) => sameNameElt.name === elt.name && sameNameEltIndex !== eltIndex));
    console.log("new table: ", newTable);
    

    【讨论】:

    • 不错的解决方案,但小尺寸(长线)并不能完全提高可读性。带有some 调用的 lambda 可能会被提取到一个命名函数中?
    • 是的,命名函数可以用于这些回调
    【解决方案4】:

    您可以使用哈希表和单个循环来映射对象或仅使用空数组,然后将结果与空数组连接。

    var data = [{ id: 0, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'C' }, { id: 3, name: 'B' }, { id: 4, name: 'B' }],
        hash = Object.create(null),
        result = Array.prototype.concat.apply([], data.map(function (o, i) {
            if (hash[o.name]) {
                hash[o.name].update && hash[o.name].temp.push(hash[o.name].object);
                hash[o.name].update = false;
                return o;
            }
            hash[o.name] = { object: o, temp: [], update: true };
            return hash[o.name].temp;
        }));
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      猜你喜欢
      • 2020-08-28
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 2021-10-26
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多