【问题标题】:How to find multiple occurrences in an array of objects and add count value?如何在对象数组中查找多次出现并添加计数值?
【发布时间】:2019-05-12 18:16:27
【问题描述】:

目前我正在尝试计算对象数组中的多次出现并将最终计数推入其中。我不想将数据存储在额外的数组中。数据应保留在现有数据中。

我要尝试添加计数的数组:

var array = [
    { artist: 'metallica', venue: 'olympiastadion' },
    { artist: 'foofighters', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'columbiahalle' },
    { artist: 'deftones', venue: 'columbiahalle' },
    { artist: 'deichkind', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'wuhlheide' },
    { artist: 'foofighters', venue: 'trabrennbahn' }
];

我当前的示例代码从数组中删除/减少,因此最终结果不符合预期:

var array = [
    { artist: 'metallica', venue: 'olympiastadion' },
    { artist: 'foofighters', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'columbiahalle' },
    { artist: 'deftones', venue: 'columbiahalle' },
    { artist: 'deichkind', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'wuhlheide' },
    { artist: 'foofighters', venue: 'trabrennbahn' }
];

array = Object.values(array.reduce((r, { artist, venue }) => {
    r[artist] = r[artist] || { artist, venue, count: 0 };
    r[artist].count++;
    return r;
}, {}));

console.log(array);

Which logs:
    { artist: 'metallica', venue: 'olympiastadion', count: 3 },
    { artist: 'foofighters', venue: 'wuhlheide', count: 2 },
    { artist: 'deftones', venue: 'columbiahalle', count: 1 },
    { artist: 'deichkind', venue: 'wuhlheide', count: 1 }

我正在尝试实现以下结果:

var array = [
    { artist: 'metallica', venue: 'olympiastadion', count: 3 },
    { artist: 'foofighters', venue: 'wuhlheide', count: 2 },
    { artist: 'metallica', venue: 'columbiahalle', count: 3 },
    { artist: 'deftones', venue: 'columbiahalle', count: 1 },
    { artist: 'deichkind', venue: 'wuhlheide', count: 1 },
    { artist: 'metallica', venue: 'wuhlheide', count: 3 },
    { artist: 'foofighters', venue: 'trabrennbahn', count: 2 }
];

感谢任何帮助,为我指明正确的方向。

感谢您的帮助!所需的解决方案是:

var array = [{ artist: 'metallica', venue: 'olympiastadion' }, { artist: 'foofighters', venue: 'wuhlheide' }, { artist: 'metallica', venue: 'columbiahalle' }, { artist: 'deftones', venue: 'columbiahalle' }, { artist: 'deichkind', venue: 'wuhlheide' }, { artist: 'metallica', venue: 'wuhlheide' }, { artist: 'foofighters', venue: 'trabrennbahn' }],
    map = array.reduce( 
        (map, { artist }) => map.set(artist, (map.get(artist) || 0) + 1),
        new Map
    ),
    array = array.map(o => Object.assign({}, o, { count: map.get(o.artist) }));

console.log(array);

【问题讨论】:

  • { artist: 'metallica', venue: 'olympiastadion', count: 3 } 真的没有意义。
  • 您想要更新的同一个数组对象,还是具有独立新对象的新数组?
  • @Andy 在这里的这个小上下文中可能没有意义。

标签: javascript arrays json object


【解决方案1】:

您可以先通过遍历所有项目来获取计数,然后将旧对象和新计数属性分配给新对象。

var array = [{ artist: 'metallica', venue: 'olympiastadion' }, { artist: 'foofighters', venue: 'wuhlheide' }, { artist: 'metallica', venue: 'columbiahalle' }, { artist: 'deftones', venue: 'columbiahalle' }, { artist: 'deichkind', venue: 'wuhlheide' }, { artist: 'metallica', venue: 'wuhlheide' }, { artist: 'foofighters', venue: 'trabrennbahn' }],
    map = array.reduce( 
        (map, { artist }) => map.set(artist, (map.get(artist) || 0) + 1),
        new Map
    ),
    result = array.map(o => Object.assign({}, o, { count: map.get(o.artist) }));

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

【讨论】:

  • 使用Map 作为计数器有什么好处吗? (因为键是按插入顺序或类似的顺序排列的?)
  • @adiga, Map#set 通过减少数组返回实例并且不需要开销。
【解决方案2】:

您可以通过以下步骤做到这一点:

  • 使用 reduce() 从数组中创建一个对象,其中包含所有唯一艺术家的数量
  • 该对象将具有不同的键 artists 并且它们的值将是它们的计数。
  • 然后在原始数组上使用forEach
  • 将所有的count设置为count数组中当前item的artist的值。

var array = [
    { artist: 'metallica', venue: 'olympiastadion' },
    { artist: 'foofighters', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'columbiahalle' },
    { artist: 'deftones', venue: 'columbiahalle' },
    { artist: 'deichkind', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'wuhlheide' },
    { artist: 'foofighters', venue: 'trabrennbahn' }
];

const unique = array.reduce((ac,{artist:a}) => (ac[a] = ac[a] + 1 || 1,ac),{});
array.forEach(x => x.count = unique[x.artist]);
console.log(array)

【讨论】:

  • 感谢您使用 array.reduce 指出这一点,这也是一个公认的解决方案。问题。如果我想对每个艺术家的出现进行额外的计数器“访问”,我该怎么做(这应该会增加每个艺术家的访问量。)?
  • 这将添加一个额外的属性访问,与来自 count 变量的相同计数器结果。每次艺术家出现时,是否有可能获得越来越多的访问?
  • @huppen 这个const unique = array.reduce((ac,{artist:a},i) => (array[i].visit = ac[a] = ac[a] + 1 || 1,ac),{}); 可能会解决你的问题。
  • 感谢您的帮助。最后的代码解决了我在评论中的问题:-)
【解决方案3】:

您可以对数组执行一次传递,将艺术家姓名映射到计数,然后第二次传递以修改每个数组项,添加与艺术家关联的计数。

var array = [
    { artist: 'metallica', venue: 'olympiastadion' },
    { artist: 'foofighters', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'columbiahalle' },
    { artist: 'deftones', venue: 'columbiahalle' },
    { artist: 'deichkind', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'wuhlheide' },
    { artist: 'foofighters', venue: 'trabrennbahn' }
];

var counts = array.reduce((counts, item) => {
  var artistName = item.artist;
  if (counts[artistName]) {
    counts[artistName] += 1;
  } else {
    counts[artistName] = 1;
  }
  
  return counts;
}, {});

array.forEach(item => item.count = counts[item.artist])

console.log(array);

为了清楚起见,.reduce 函数很冗长,但可以大大缩短:

var array = [
    { artist: 'metallica', venue: 'olympiastadion' },
    { artist: 'foofighters', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'columbiahalle' },
    { artist: 'deftones', venue: 'columbiahalle' },
    { artist: 'deichkind', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'wuhlheide' },
    { artist: 'foofighters', venue: 'trabrennbahn' }
];

var counts = array.reduce((counts, item) => (counts[item.artist] = counts[item.artist] || 1, counts), {});

console.log(counts);

如果你想创建一个数组而不是修改旧数组中的对象,那么你可以复制每个对象和数组:

var array = [
    { artist: 'metallica', venue: 'olympiastadion' },
    { artist: 'foofighters', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'columbiahalle' },
    { artist: 'deftones', venue: 'columbiahalle' },
    { artist: 'deichkind', venue: 'wuhlheide' },
    { artist: 'metallica', venue: 'wuhlheide' },
    { artist: 'foofighters', venue: 'trabrennbahn' }
];

var counts = {
  "metallica": 3,
  "foofighters": 2,
  "deftones": 1,
  "deichkind": 1
}

var newArray = array.map(item => ({...item, count: counts[item.artist]}))

console.log(newArray);
console.log(array);

【讨论】:

    【解决方案4】:

    您可以在数组上迭代两次。

    var array = [
        { artist: 'metallica', venue: 'olympiastadion' },
        { artist: 'foofighters', venue: 'wuhlheide' },
        { artist: 'metallica', venue: 'columbiahalle' },
        { artist: 'deftones', venue: 'columbiahalle' },
        { artist: 'deichkind', venue: 'wuhlheide' },
        { artist: 'metallica', venue: 'wuhlheide' },
        { artist: 'foofighters', venue: 'trabrennbahn' }
    ];
    
    array.forEach(a => {
      if (!a.hasOwnProperty('count')) {
        Object.assign(a, { count: 0 });
      }
      array.forEach(b => {
        if (a.artist === b.artist) {
          a.count++;
        }
      });
    });
    
    console.log(array);
    

    【讨论】:

      猜你喜欢
      • 2019-04-17
      • 1970-01-01
      • 1970-01-01
      • 2021-04-25
      • 2011-04-29
      • 2019-10-27
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多