j_d*_*j_d 15 javascript arrays ecmascript-6
所以我有两个数组:
const allLanguages = [ 'ES', 'EN', 'DE' ]
const usedLanguages = [ { id: 1, lang: 'EN' } ]
Run Code Online (Sandbox Code Playgroud)
生成新阵列的最快方法是什么,这两者是不同的?在旧式JavaScript中,你必须在另一个for循环中进行for循环,我认为......
例如:
const availableLanguages = [ 'ES', 'DE' ]
Run Code Online (Sandbox Code Playgroud)
Nen*_*car 24
您可以使用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)Run Code Online (Sandbox Code Playgroud)
您还可以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)Run Code Online (Sandbox Code Playgroud)
小智 9
受到@Ori Drori出色答案的启发,这是一个纯粹的基于集合的解决方案。
const all = new Set(allLanguages);
const used = new Set(usedLanguages.map(({lang}) => lang));
const availableLanguages = setDifference(all, used);
Run Code Online (Sandbox Code Playgroud)
哪里
const setDifference = (a, b) => new Set([...a].filter(x => !b.has(x)));
Run Code Online (Sandbox Code Playgroud)
availableLanguages将是一个集合,因此要将其作为数组使用,您需要对其进行处理Array.from或[...map]对其进行处理。
如果想让所有功能正常运行,那么
const not = fn => x => !fn(x);
const isIn = set => x => set.has(x);
Run Code Online (Sandbox Code Playgroud)
现在写
const setDifference = (a, b) => new Set([...a].filter(not(isIn(b))));
Run Code Online (Sandbox Code Playgroud)
有些人可能会认为它更具语义或可读性。
但是,这些解决方案并不令人满意,并且可能不是最佳的。即使Set#has是O(1),相比O(n)于find或some,整体表现依然O(n),因为我们经历的所有元素都具有迭代a。这将是更好的删除元素b从a,因为有人建议在另一个答案。这是
const setDifference = (a, b) => {
const result = new Set(a);
b.forEach(x => result.delete(x));
return result;
}
Run Code Online (Sandbox Code Playgroud)
我们不能使用它,reduce因为它在集合上不可用,并且我们不想将集合转换为数组来使用它。但是我们可以使用forEach,它在设备上可用。如果a较大且b较小,则该替代方案将是优选的。
将来的JS版本很可能会内置此功能,您可以说
const availableLanguages = all.difference(used)
Run Code Online (Sandbox Code Playgroud)
最后,如果我们有兴趣探索更多ES6功能,可以将其编写为生成非重复值的生成器,如下所示:
function* difference(array, excludes) {
for (let x of array)
if (!excludes.includes(x)) yield x;
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以写
console.log([...difference(allLanguages, usedLanguages)]);
Run Code Online (Sandbox Code Playgroud)
如果有很长的语言列表,也许是一种一一出现,并且您想获得一小部分未使用的语言,则可能建议使用此解决方案。
如果要O(1)在不使用集合的情况下查找排除列表,则经典方法是预先计算字典:
const dict = Object.assign({},
...usedLanguages.map(({lang}) => ({[lang]: true})));
const availableLanguages = allLanguages.filter(lang => lang in dict);
Run Code Online (Sandbox Code Playgroud)
如果这种计算字典的方式对您来说太神秘了,那么有些人会使用reduce:
const dict = usedLanguages.reduce((obj, {lang}) => {
obj[lang] = true;
return obj;
}, {});
Run Code Online (Sandbox Code Playgroud)
Nina喜欢用逗号运算符写成
const dict = usedLanguages.reduce((obj, {lang}) => (obj[lang] = true, obj), {});
Run Code Online (Sandbox Code Playgroud)
这样可以节省一些花括号。
或者,由于JS仍然有for循环:-):
const dict = {};
for (x of usedLanguages) {
dict[x.lang] = true;
}
Run Code Online (Sandbox Code Playgroud)
嗨,您是谁说过要使用ES6的人。
您可以使用以下代码:
availableLanguages = allLanguages.filter((lang1) => !usedLanguages.some((lang2) => lang2.lang === lang1))
Run Code Online (Sandbox Code Playgroud)
该some函数相对于此更为人所知find,更适合于您要检查数组中是否满足条件的情况.