Javascript 在对象数组中,按一个属性分组,并计算关键字在另一个属性中的出现次数?

Javascript 在对象数组中,按一个属性分组,并计算关键字在另一个属性中的出现次数?,javascript,algorithm,optimization,Javascript,Algorithm,Optimization,我有一个对象数组 [ { hashtag: [ 'yo' ], type: [] }, { hashtag: [ 'yo2' ], type: [] }, { hashtag: [ 'yo3' ], type: [] }, { hashtag: [ 'yo4' ], type: [] }, { hashtag: [ 'yo4' ], type: [] }, { hashtag: [ 'yo5' ], type: [ 'email' ] },

我有一个对象数组

[ 
    { hashtag: [ 'yo' ], type: [] },
    { hashtag: [ 'yo2' ], type: [] },
    { hashtag: [ 'yo3' ], type: [] },
    { hashtag: [ 'yo4' ], type: [] },
    { hashtag: [ 'yo4' ], type: [] },
    { hashtag: [ 'yo5' ], type: [ 'email' ] },
    { hashtag: [ 'yo5' ], type: [ 'link' ] },
    { hashtag: [ 'asdasdasd' ], type: [ 'email' ] },
    { hashtag: [ 'yo5' ], type: [ 'link' ] },
    { hashtag: [ 'yo6' ], type: [ 'link' ] },
    { hashtag: [ 'yo6' ], type: [ 'link' ] },
    { hashtag: [ 'yo7' ], type: [ 'link' ] },
    { hashtag: [ 'book', 'hello', 'yo5' ], type: [ 'link' ] } 
];
每个hashtag值可以包含字符串数组。我需要得到所有具有确切类型的唯一hashtag数组,并对它们进行计数。预期产出:

[ 
    { hashtag: 'yo5', sum: 3 },
    { hashtag: 'yo6', sum: 2 },
    { hashtag: 'yo7', sum: 1 },
    { hashtag: 'book', sum: 1 },
    { hashtag: 'hello', sum: 1 } 
]
我写了代码,但对我来说,似乎还不够优化。有没有办法让它变得更好

const type = 'link';

const enter = [ 
    { hashtag: [ 'yo' ], type: [] },
       ...
    { hashtag: [ 'book', 'hello', 'yo5' ], type: [ 'link' ] } 
];

const filteredByType = enter.filter((el) => {
    return el.type.includes(type)
});

const newArr = [];

filteredByType.map((el) => {
  for (let i = 0; i < el.hashtag.length; i++) {
    const z = newArr.filter((e) => {
        return e.hashtag === el.hashtag[i]
    });
    if (z.length) {
      const p = newArr.findIndex((obj) => {
        return obj.hashtag === el.hashtag[i];
      });
      newArr[p].sum += 1;
    } else {
      newArr.push({
        hashtag: el.hashtag[i],
        sum: 1
      })
    }
  }
});

console.log('newArr', newArr);
正在运行的示例

您可以获取一个,计算发生次数并从中构建一个新数组

常数 getCount=array,type=>array.from 数据还原 映射,o=>o.type.includeType ? o、 hashtag.reducem,v=>m.setv,m.getv | | 0+1,map :地图, 新地图 , [hashtag,sum]=>{hashtag,sum} , 数据=[{hashtag:['yo'],类型:[]},{hashtag:['yo2'],类型:[]},{hashtag:['yo3'],类型:[]},{hashtag:['yo4'],类型:[]},{hashtag:['yo5'],类型:['email']},{hashtag['yo5'],类型:['link']},{hashtag asdasd'],类型:['yo4'],类型:['email'],类型:['link']},{标签:['yo6'],类型:['link']},{标签:['yo7'],类型:['link']},{标签:['book','hello','yo5'],类型:['link']}; console.loggetCountdata,“link”; console.loggetCountdata,“电子邮件”; .as console wrapper{max height:100%!important;top:0;}您可以使用a,计算发生次数并从中构建新数组

常数 getCount=array,type=>array.from 数据还原 映射,o=>o.type.includeType ? o、 hashtag.reducem,v=>m.setv,m.getv | | 0+1,map :地图, 新地图 , [hashtag,sum]=>{hashtag,sum} , 数据=[{hashtag:['yo'],类型:[]},{hashtag:['yo2'],类型:[]},{hashtag:['yo3'],类型:[]},{hashtag:['yo4'],类型:[]},{hashtag:['yo5'],类型:['email']},{hashtag['yo5'],类型:['link']},{hashtag asdasd'],类型:['yo4'],类型:['email'],类型:['link']},{标签:['yo6'],类型:['link']},{标签:['yo7'],类型:['link']},{标签:['book','hello','yo5'],类型:['link']}; console.loggetCountdata,“link”; console.loggetCountdata,“电子邮件”; .as控制台包装器{max height:100%!important;top:0;}如果按总和计算实际上是指计数,则可以将Map与Array.prototype.reduce一起使用,以按哈希标记值对数组进行分组

因此,假设您的类型不包含重复项,您可能会得到如下结果:

常量src=[{hashtag:[yo],type:[]},{hashtag:[yo2],type:[]},{hashtag:[yo3],type:[]},{hashtag:[yo4],type:[]},{hashtag:[yo5],type:[email]},{hashtag yo5],type:[link]},{hashtag asdasdasd],type:[email]},{hashtag:[yo5],type:[link link][yo5],type:[link hashtag yo6],type:[yo7],hashtag[book,hello,yo5],键入:[link]}, groupSearch=\u类型=> […src .reduceAC,{hashtag,type}=>{ 常量增量=+type.includes\u type 增量&& hashtag.forEachtag=>{ 常量组=acc.gettag 组 ?group.sum+=增量 :acc.settag,{hashtag:tag,sum:increment} } 返回acc },新地图 价值观 ] console.loggroupSearch'link' .as console wrapper{min height:100%;}如果通过sum实际上指的是count,则可以将Map与Array.prototype.reduce一起使用,以按hashtag值对数组进行分组

因此,假设您的类型不包含重复项,您可能会得到如下结果:

常量src=[{hashtag:[yo],type:[]},{hashtag:[yo2],type:[]},{hashtag:[yo3],type:[]},{hashtag:[yo4],type:[]},{hashtag:[yo5],type:[email]},{hashtag yo5],type:[link]},{hashtag asdasdasd],type:[email]},{hashtag:[yo5],type:[link link][yo5],type:[link hashtag yo6],type:[yo7],hashtag[book,hello,yo5],键入:[link]}, groupSearch=\u类型=> […src .reduceAC,{hashtag,type}=>{ 常量增量=+type.includes\u type 增量&& hashtag.forEachtag=>{ 常量组=acc.gettag 组 ?group.sum+=增量 :acc.settag,{hashtag:tag,sum:increment} } 返回acc },新地图 价值观 ] console.loggroupSearch'link'
.作为控制台包装器{最小高度:100%;}我这么做了,不知道它的性能如何

常数数据= [{hashtag:['yo'],类型:[]} ,{hashtag:['yo2'],类型:[]} ,{hashtag:['yo3'],类型:[]} ,{hashtag:['yo4'],类型:[]} ,{hashtag:['yo4'], 类型:[]} ,{hashtag:['yo5'],类型:['email']} ,{hashtag:['yo5'],类型:['link']} ,{hashtag:['asdasdasd'],类型:['email']} ,{hashtag:['yo5'],类型:['link']} ,{hashtag:['yo6'],类型:['link']} ,{hashtag:['yo6'],类型:['link']} ,{hashtag:['yo7'],类型:['link']} ,{hashtag:['book','hello','yo5'],类型:['link']} ] const getCount=arr,typeK=> arr.reduceres,{hashtag,type}=>[…res,…type.includestypeK?hashtag:[],[] 分类 .reduceres,val,i,{[i-1]:last}=> { 如果last==val res[res.length-1]。求和++ else res.push{hastag:val,sum:1} 返回res },[] console.log'link=',getCountdata'link' console.log'email=',getCountdata'email'
.作为控制台包装{max height:100%!important;top:0;}我这么做了,不知道它是如何运行的

常数数据= [{hashtag:['yo'],类型:[]} ,{hashtag:['yo2'],类型:[]} ,{hashtag:['yo3'],类型:[]} ,{hashtag:['yo4'],类型:[]} ,{hashtag:['yo4'],类型:[]} ,{hashtag:['yo5'],类型:['email']} ,{hashtag:['yo5'],类型:['link']} ,{hashtag:['asdasdasd'],类型:['email']} ,{hashtag:['yo5'],类型:['link']} ,{hashtag:['yo6'],类型:['link']} ,{hashtag:['yo6'],类型:['link']} ,{hashtag:['yo7'],类型:['link']} ,{hashtag:['book','hello','yo5'],类型:['link']} ] const getCount=arr,typeK=> arr.reduceres,{hashtag,type}=>[…res,…type.includestypeK?hashtag:[],[] 分类 .reduceres,val,i,{[i-1]:last}=> { 如果last==val res[res.length-1]。求和++ else res.push{hastag:val,sum:1} 返回res },[] console.log'link=',getCountdata'link' console.log'email=',getCountdata'email' .作为控制台包装{最大高度:100%!重要;顶部:0;}另一种方式

常数数据= [{hashtag:['yo'],类型:[]} ,{hashtag:['yo2'],类型:[]} ,{hashtag:['yo3'],类型:[]} ,{hashtag:['yo4'],类型:[]} ,{hashtag:['yo4'],类型:[]} ,{hashtag:['yo5'],类型:['email']} ,{hashtag:['yo5'],类型:['link']} ,{hashtag:['asdasdasd'],类型:['email']} ,{hashtag:['yo5'],类型:['link']} ,{hashtag:['yo6'],类型:['link']} ,{hashtag:['yo6'],类型:['link']} ,{hashtag:['yo7'],类型:['link']} ,{hashtag:['book','hello','yo5'],类型:['link']} ] const getCount=arr,typeK=> Object.entriesarr.reducer,{hashtag,type}=> { 如果type.includeType hashtag.forEachh=>{r[h]=r[h]??0;r[h]+} 返回r },{}.map[k,v]=>{hashtag:k,sum:v} console.log'link=',getCountdata'link' console.log'email=',getCountdata'email' .作为控制台包装{最大高度:100%!重要;顶部:0;}另一种方式

常数数据= [{hashtag:['yo'],类型:[]} ,{hashtag:['yo2'],类型:[]} ,{hashtag:['yo3'],类型:[]} ,{hashtag:['yo4'],类型:[]} ,{hashtag:['yo4'],类型:[]} ,{hashtag:['yo5'],类型:['email']} ,{hashtag:['yo5'],类型:['link']} ,{hashtag:['asdasdasd'],类型:['email']} ,{hashtag:['yo5'],类型:['link']} ,{hashtag:['yo6'],类型:['link']} ,{hashtag:['yo6'],类型:['link']} ,{hashtag:['yo7'],类型:['link']} ,{hashtag:['book','hello','yo5'],类型:['link']} ] const getCount=arr,typeK=> Object.entriesarr.reducer,{hashtag,type}=> { 如果type.includeType hashtag.forEachh=>{r[h]=r[h]??0;r[h]+} 返回r },{}.map[k,v]=>{hashtag:k,sum:v} console.log'link=',getCountdata'link' console.log'email=',getCountdata'email'
.as控制台包装{max height:100%!important;top:0;}另一个使用双reduce的解决方案。我们过滤掉那些不包括我们的目标类型的值,将结果折叠成像{yo5:3,yo6:2,yo7:1,book:1,hello:1}这样的对象,将其条目映射到{hashtag,sum}格式:

const tagCountByType=targetType=>xs=> Object.entries xs.filter{type}=>type.includes targetType 减少 a、 {hashtag}=>hashtag.reduce a,tag=>a[tag]=a[tag]| | 0+1,a,a, {} .map[标签,总和] =>{hashtag,sum} 常量输入为[[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0'链接']},{hashtag:['yo6'],类型:['link']},{hashtag:['yo7'],类型:['link']},{hashtag:['book','hello','yo5'],类型:['link']}] console.log“link:”,tagCountByType“link”输入 console.log“email:”,tagCountByType“email”输入
.as控制台包装{max height:100%!important;top:0}另一个使用双reduce的解决方案。我们过滤掉那些不包括我们的目标类型的值,将结果折叠成像{yo5:3,yo6:2,yo7:1,book:1,hello:1}这样的对象,将其条目映射到{hashtag,sum}格式:

const tagCountByType=targetType=>xs=> Object.entries xs.filter{type}=>type.includes targetType 减少 a、 {hashtag}=>hashtag.reduce a,tag=>a[tag]=a[tag]| | 0+1,a,a, {} .map[hashtag,sum]=>{hashtag,sum} 常量输入为[[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0'链接']},{hashtag:['yo6'],类型:['link']},{hashtag:['yo7'],类型:['link']},{hashtag:['book','hello','yo5'],类型:['link']}] console.log“link:”,tagCountByType“link”输入 console.log“email:”,tagCountByType“email”输入

作为控制台包装{max height:100%!important;top:0}如果只有唯一的,那么应该计算类型值,hashtag:'yo5'不应该有各自的总和:2,因为'email'和'link'只有两个唯一值吗?@YevgenGorbunkov应该计算确切的类型,我修正了一点我的问题。在我的例子中,结果是正确的,那么,“which have exact type”是什么意思?@YevgenGorbunkov在我的代码中,我在第一行中以const type='link'的形式传递它。所以我需要:从类型为link的数组中获取所有hashtag和包含此hashtag的对象的总数如果只有唯一的,那么应该计算类型值,hashtag'yo5'不应该有各自的总和:2,因为'email'和'link'只有两个唯一的值?@YevgenGorbunkov它应该为确切的类型计算,我修正了一点我的问题。在我的例子中,结果是正确的,那么,“which have exact type”是什么意思?@YevgenGorbunkov在我的代码中,我在第一行中以const type='link'的形式传递它。所以我需要:从数组中的类型是链接,得到所有哈希标签和包含这个哈什塔基的对象的总数,在你的代码中看不到你认为它应该有精确的类型。但你如何使用地图和集合是很有趣的。我会尝试在我的生活中使用它code@angelzzz我得到了你的观点,调整了我的解决方案,以准确地给出预期的输出。@安杰兹:考虑我在我的答案的最新编辑中添加的一个小的逃生舱,这会极大地提高性能。在你的代码中你看不到它应该有精确的类型。但你如何使用地图和集合是很有趣的。我会尝试在我的生活中使用它code@angelzzz我得到了你的观点,调整了我的解决方案,以准确地给出预期的输出。@安杰兹:考虑一下我在我的答案的最新编辑中添加的一个小的逃生舱,这大大提高了性能,没有达到预期的效果。它应该考虑类型。但解决办法非常简单useful@angelzzz,对不起,我错过了打字部分。请看编辑。谢谢!工作很好,但没有按预期工作。它应该考虑类型。但解决办法非常简单useful@angelzzz,对不起,我错过了打字部分。请看编辑。谢谢!这一点也很有效。@YevgenGorbunkov确实,我也完全忽略了这一点。我纠正了;“这一点也一样。”叶夫根戈尔邦科夫说真的,我也完全错过了这一点。我纠正了;至于性能,我预计它可能会相对缓慢,因为.sort本身就相当昂贵。不过,我可能错了,因为它不能提供预期的输出,所以我无法将其与其他产品进行比较。@YevgenGorbunkov事实上,我完全忽略了这一点。我纠正了@YevgenGorbunkov预期输出在原始问题和中提供jsfiddle@angelzzz:我的意思是,这个特定的答案没有提供您指定的预期输出,这就是为什么不能将苹果与其他解决方案进行比较,因为它们实现了期望的输出。但是,一个假设:上面的解决方案是最慢的解决方案之一,而最快的是Nina发布的解决方案,而我发布的解决方案——在不同的基准测试中,她的或我的解决方案显示出最快的性能。至于性能,我预计它可能会相对缓慢,因为.sort非常简单
独自沉思。不过,我可能错了,因为它不能提供预期的输出,所以我无法将其与其他产品进行比较。@YevgenGorbunkov事实上,我完全忽略了这一点。我纠正了@YevgenGorbunkov预期输出在原始问题和中提供jsfiddle@angelzzz:我的意思是,这个特定的答案没有提供您指定的预期输出,这就是为什么不能将苹果与其他解决方案进行比较,因为它们实现了期望的输出。但是,一个假设:上面的解决方案是最慢的解决方案之一,而最快的是Nina发布的解决方案,而我发布的解决方案——在不同的基准运行中,她的或我的解决方案显示出最快的性能。