我有以下数组:
let a = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer", "egg"]
let b = ["egg", "salt", "beer"]
如何检查b
中来自a
的单词多少次?
在上述情况下,答案将是2次,因为来自b的所有单词都包含两次。但是,如果a
如下:
let a = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer"]
答案是1,因为egg
仅包含一次。
在这里,时间效率是关键,因为我将处理包含超过10万个元素的列表。
答案 0 :(得分:1)
您可以使用reduce
方法:
let words = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer", "egg"]
var initialValue = {};
var reducer = function(word, index){
if(!word[index]){
word[index] = 1;
} else{
word[index] = word[index] + 1;
}
return word;
}
var results = words.reduce(reducer, initialValue);
console.log(results);
答案 1 :(得分:1)
let a = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer", "egg"]
let b = ["egg", "salt", "beer"]
let counts ={}
b.forEach(word=>{
counts[word] = a.filter(item => item ===word).length
});
console.log(counts)
答案 2 :(得分:1)
这是一个非常简单的解决方案,其结果将列出第二个列表中的所有内容,对于不在数据中的内容包括零。
在a
和b
的长度总和中,性能应该几乎是线性的。 (a in o
中可能存在一些难以测量的非线性,但是我不知道引擎内部使用的算法,所以我不确定。)
请注意,bs.reduce((o, b) => Object.assign(o, {[b]: 0}), {})
仅被调用一次,以形成第一个reduce
的初始累加器;这不是嵌套的减少。
const counts = (as, bs) => as.reduce(
(o, a) => Object.assign(o, a in o ? {[a]: o[a] + 1} : {}),
bs.reduce((o, b) => Object.assign(o, {[b]: 0}), {})
)
const a = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer", "egg"]
const b = ["egg", "salt", "beer", "tofu"]
console.log(counts(a, b))
但是实际性能可能会低于某些手动滚动的for
或while
循环。 reduce
的表现根本不如它们。
这实际上并没有回答所问的问题。我误解了这个问题。更新的版本是
const minMatch = (as, bs) => Math.min(...Object.values(as.reduce(
(o, a) => Object.assign(o, a in o ? {[a]: o[a] + 1} : {}),
bs.reduce((o, b) => Object.assign(o, {[b]: 0}), {})
)))
const a = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer", "egg"]
const b = ["egg", "salt", "beer"]
console.log(minMatch(a, b))
答案 3 :(得分:1)
使用Array.reduce()
迭代数组a
。将数组b
转换为Map,并将其用作reduce的初始值。
如果Map中存在数组a
中的一项,则增加该值。如果没有,请忽略它。完成后,通过Math.min()
分布地图的值:
const a = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer", "egg"]
const b = ["egg", "salt", "beer"]
const result = Math.min(
...a.reduce((m, s) =>
m.has(s) ? m.set(s, (m.get(s) || 0) + 1) : m
, new Map(b.map(s => [s, 0]))
).values()
);
console.log(result);
答案 4 :(得分:0)
该方法可以是在遍历数组A时构造一个哈希映射,而在遍历数组B时访问该哈希映射(请参见下面的代码)
let a = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer", "egg"]
let b = ["egg", "salt", "beer"]
let hashMap = {};
for(let element in a){
if(!hashMap[a[element]])
hashMap[a[element]] = 0;
hashMap[a[element]]++;
}
var minVal = a.length;
for(let element in b){
if(hashMap[b[element]])
minVal = Math.min(minVal, hashMap[b[element]]);
}
console.log(minVal);
答案 5 :(得分:0)
这应该有效
let a = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer", "salt"];
let b = ["egg", "salt"];
const products = a.reduce((result, current) => {
b.forEach(word => {
if (word === current) {
result[word] = result[word] ? result[word] + 1 : 1;
}
})
return result;
}, {});
console.log(products); // { egg: 1, salt: 3 }
答案 6 :(得分:0)
使用数字for
循环将a
简化为普通对象:
let a = ["egg", "pepper", "salt", "bacon", "beer", "salt", "water", "beer", "egg"]
let b = ["egg", "salt", "beer"]
const keys = b.reduce((o, k) => Object.assign(o, { [k]: true }), {})
const { length } = a
const values = {}
for (let i = 0; i < length; i++) {
const key = a[i]
if (key in keys) {
if (key in values) {
values[key]++
} else {
values[key] = 1
}
}
}
console.log(values)
数字for
循环比reduce
和forEach
之类的Array
方法要快,并且通常比for...of
和for...in
要快不使用iterators或反射来枚举数组的键。
keys
对象的作用是根据b
的大小将查找从O(n)减少到〜O(1),使您的整体复杂度约为 O(n) 。如果b
也很大,则也可以使用数字for
循环来创建keys
,并注意查找可能会从〜O(1)恶化为O(log(n)),这会导致将使您的总时间复杂度为 O(n log(n))。