所以我有两个数组:
const allLanguages = [ 'ES', 'EN', 'DE' ]
const usedLanguages = [ { id: 1, lang: 'EN' } ]
生成新阵列的最快方法是什么,这两者之间的区别是什么?在旧式的JavaScript中,你必须在另一个for循环中进行for循环,我认为......
例如:
const availableLanguages = [ 'ES', 'DE' ]
答案 0 :(得分:22)
您可以使用filter()
和find()
返回已过滤的数组。
const allLanguages = [ 'ES', 'EN', 'DE' ]
const usedLanguages = [ { id: 1, lang: 'EN' } ]
var result = allLanguages.filter(e => !usedLanguages.find(a => e == a.lang));
console.log(result)

您还可以map()
第二个数组,然后使用includes()
过滤掉重复数据。
const allLanguages = [ 'ES', 'EN', 'DE' ]
const usedLanguages = [ { id: 1, lang: 'EN' } ].map(e => e.lang);
var result = allLanguages.filter(e => !usedLanguages.includes(e));
console.log(result)

答案 1 :(得分:8)
受到@Ori Drori的出色答案的启发,这是一个纯粹的基于集合的解决方案。
const all = new Set(allLanguages);
const used = new Set(usedLanguages.map(({lang}) => lang));
const availableLanguages = setDifference(all, used);
,其中
const setDifference = (a, b) => new Set([...a].filter(x => !b.has(x)));
availableLanguages
将是一个集合,因此要将其作为数组使用,您需要在其上执行Array.from
或[...map]
。
如果想要全部功能,那么
const not = fn => x => !fn(x);
const isIn = set => x => set.has(x);
现在写
const setDifference = (a, b) => new Set([...a].filter(not(isIn(b))));
有些人可能认为更具语义或可读性。
然而,这些解决方案有些不尽如人意,可能不是最理想的。即使Set#has
为O(1)
,与O(n)
或find
的{{1}}相比,整体效果仍为some
,因为我们必须迭代通过O(n)
的所有元素。最好从a
中删除b
中的元素,如另一个答案所示。这将是
a
我们无法使用const setDifference = (a, b) => {
const result = new Set(a);
b.forEach(x => result.delete(x));
return result;
}
,因为套装无法使用reduce
,我们不希望必须将该套件转换为数组才能使用它。但是我们可以使用forEach
,它可以在集合中使用。如果a
更大且b
更小,则此替代方案更为可取。
很可能JS的某些未来版本将内置此功能,您只需说出
即可const availableLanguages = all.difference(used)
最后,如果我们有兴趣探索更多ES6功能,我们可以将其编写为生成非重复值的生成器,如
function* difference(array, excludes) {
for (let x of array)
if (!excludes.includes(x)) yield x;
}
现在我们可以写
console.log([...difference(allLanguages, usedLanguages)]);
如果有很长的语言列表,可能会推荐使用此解决方案,可能会逐个出现,并且您希望获得未使用的语言流。
如果想要O(1)
在不使用集合的情况下查找排除列表,那么经典的方法是预先计算字典:
const dict = Object.assign({},
...usedLanguages.map(({lang}) => ({[lang]: true})));
const availableLanguages = allLanguages.filter(lang => lang in dict);
如果这种计算字典的方式对你来说太神秘了,那么有些人会使用reduce
:
const dict = usedLanguages.reduce((obj, {lang}) => {
obj[lang] = true;
return obj;
}, {});
Nina喜欢使用逗号运算符编写
const dict = usedLanguages.reduce((obj, {lang}) => (obj[lang] = true, obj), {});
可以节省一些花括号。
或者,因为JS仍然有for
个循环: - ):
const dict = {};
for (x of usedLanguages) {
dict[x.lang] = true;
}
嘿,你是那个说你想用ES6的人。
答案 2 :(得分:6)
您可以使用以下代码:
availableLanguages = allLanguages.filter((lang1) => !usedLanguages.some((lang2) => lang2.lang === lang1))
some
函数与find
相比鲜为人知,更适合于您想要检查数组中是否满足条件的情况。
答案 3 :(得分:3)
使用usedLanguages
迭代Array#reduce
,new Set(allLanguages)
作为起始值。从used
每次迭代设置中删除语言。将结果传播到数组中。复杂度为O(n + m),其中n是usedLanguages
数组的长度,m是allLanguages
的长度:
const allLanguages = [ 'ES', 'EN', 'DE' ];
const usedLanguages = [{ id: 1, lang: 'EN' }];
const result = [...usedLanguages.reduce((r, { lang }) => {
r.delete(lang);
return r;
}, new Set(allLanguages))];
console.log(result);