Javascript 查找具有频率值的二维关键字数组的更快方法

Javascript 查找具有频率值的二维关键字数组的更快方法,javascript,arrays,performance,Javascript,Arrays,Performance,我有没有更快的方法来计算二维数组中所有元素的所有频率?如此示例: var array = [["a", "b"]["c", "d"]["b", "d"]["c", "a", "b"], ["a", "b", "c", "d"]; 我的预期结果是一个包含关键字和频率值的对象数组 像这样, result = [{ keyword: "a", frequency: 3 }, { keyword: "b", f

我有没有更快的方法来计算二维数组中所有元素的所有频率?如此示例:

var array = [["a", "b"]["c", "d"]["b", "d"]["c", "a", "b"], ["a", "b", "c", "d"];
我的预期结果是一个包含关键字和频率值的对象数组
像这样,

result = [{ keyword: "a",
            frequency: 3
          }, {
            keyword: "b",
            frequency: 4
          }, ... ];
以下是我的解决方案:

函数生成数据(记录){
var数据=[];
对于(变量i=0;i
您可以使用
.reduce()
以对象的形式获得所需的频率:

let数据=[
[“a”、“b”],
[“c”、“d”],
[“b”、“d”],
[“c”、“a”、“b”],
[“a”、“b”、“c”、“d”]
];
让result=[].concat(…data).reduce((r,c)=>(r[c]=(r[c]| | 0)+1,r),{});

控制台日志(结果)您可以通过将单词存储在映射中,然后在最后在映射上迭代来降低复杂性。这样可以避免对每个单词的结果进行迭代

旧复杂性
O(N*M*R)
array*每组中的单词*结果 新复杂性
O(N*M+R)

注意:
Array.prototype.concat
,我相信它的运行时间很长。对于每个concat,将创建一个新对象,并将现有值和新值复制到该新对象中并返回。这就是为什么不修改旧阵列的原因。因此,值被反复读取

var数组=[[a”,“b”],[c”,“d”],[b”,“d”],[c”,“a”,“b”],[a”,“b”,“c”,“d”];
var resultMap={};
array.forEach(函数(关键字){
关键词.forEach(函数(word,i){
如果(结果映射[字]){
结果映射[word]。频率=结果映射[word]。频率+1;
}
否则{
结果映射[字]={
关键词:单词,
频率:1
};
}
});
});

log(Object.values(resultMap))您可以使用和将其简化为如下内容:

const input=[[“a”、“b”]、[“c”、“d”]、[“b”、“d”]、[“c”、“a”、“b”]、[“a”、“b”、“c”、“d”]]
,output=input.flat().reduce((acc,a)=>
((acc[a]=acc[a]|{关键字:a,频率:0})[“频率”]+,acc)
,{})

console.log(Object.values(output))
这里我将原始数组转换为字符串,然后将字符计数到另一个数组中

const数组=[
[“a”、“b”],
[“c”、“d”],
[“b”、“d”],
[“c”、“a”、“b”],
[“a”、“b”、“c”、“d”]
]
让result=array.join().replace(/[]/g').split(“,”)
让计数={}
result.forEach(c=>count[c]=(count[c]| | 0)+1)

log(count)
如果这真的是一个瓶颈,并且从计数中挤出速度是值得的,而代码没有函数解决方案那么漂亮,那么在今天的javascript引擎中,你将很难击败
循环。在我的测试中,这大约是使用
reduce()
的两倍:

var数组=[[a”,“b”],[c”,“d”],[b”,“d”],[c”,“a”,“b”],[a”,“b”,“c”,“d”];
让计数=新映射()
for(设i=0;i

JSperf

虽然这是一种很酷的方法,但是如果您将性能与OPs解决方案进行比较,它会得到改进,因为他们说“更快”意味着更少的代码,或者意味着更少的计算周期。这应该快得多,感谢您的想法!我将尝试使用我的数据集进行测试,并找到运行时间。这一次实际上更快,我使用我原始问题中的代码片段进行了测试。编辑以使其实际工作。当天的专业提示:提交前检查代码错误!阅读adiga的回答后,将迭代更改为Object.values。性能非常有趣,代码清晰,易于阅读。谢谢!这样更快?这里的
替换
有什么用?我只使用
array.join().split(“,”)
得到了非常相同的结果。虽然我喜欢您的解决方案,因为它与其他解决方案有点不同,但与reduce和for循环相比,它仍然是最慢的解决方案。
var array = [["a", "b"],["c", "d"],["b", "d"],["c", "a", "b"], ["a", "b", "c", "d"]];

let counts = new Map()
for (let i = 0; i < array.length; i++){
    for (let j = 0; j < array[i].length; j++){
        let n = counts.get(array[i][j]) || 0
        counts.set(array[i][j], n + 1)
    }
}