let str = 'bib'
let list = ['rabbit','bibe','bundle']
for(let i = 0; i < list.length;i++){
for(let j = 0; j < list[i].length; j++){
let foundIndex = str.indexOf(list[i][j])>-1
if(foundIndex === -1){
list.splice(foundIndex,1)
}else if(foundIndex){
console.log(list[i])
}
}
}
rabbit
bibe
这是另一个解决方案,如果我们将字母“bib”排序为“bbi”。
如果我们对列表 ["rabbit","bibe","bundle"] 做类似的事情变成 ["abbirt", "bbei" 和 "bdelnu"]。如果我们过滤不在“bib”中的字母,列表将缩小为 ["bbi","bbi","b"]。我们现在可以做的是检查结果列表中是否出现“bbi”。
这是上述的中间实现:
let str = 'bib';
let list = ['rabbit','bibe','bundle'];
let str2 = [...str].sort().join('');
let result =list.filter( function (w) {
let w2 = [...w].filter( c => str.indexOf(c) !== -1 ).sort().join('');
return w2.indexOf(str2) !== -1;
} );
console.log(JSON.stringify(result));
这是相同的代码,但打了更多的高尔夫球:
let str = 'bib';
let list = ['rabbit','bibe','bundle'];
let result = list.filter( w => [...w].filter( c => str.indexOf(c) !== -1 ).sort().join('').indexOf([...str].sort().join('')) !== -1);
console.log(JSON.stringify(result));
一个简单的解决方案是计算给定字符串中每个唯一字符的数量,然后基于此过滤元素:如果一个元素具有所有这些字符,每个字符的数量相同或更高,那么它应该被保留。
首先,声明一个辅助函数:
function stringToMap(string) {
return [...string].reduce((map, char) => {
map[char] = map[char] + 1 || 1;
return map;
}, {});
}
它将返回一个如下所示的对象:
{
b: 2,
i: 1
}
Array
对象有一个非常方便的方法,名为 .every()
当且仅当回调函数对所有元素返回 true 时,它返回 true
。我们想利用它,所以我们使用 Object.entries()
: 将上面的对象转换为键值对数组
const charsAndAmount = Object.entries(stringToMap(str));
// The object above now looks like this:
[
['b', 2],
['i', 1]
]
我们对列表的每个元素做同样的事情(不是
Object.entries()
部分;我们不需要他们的 .every()
):
const charMaps = list.map(stringToMap);
[
{ r: 1, a: 1, b: 2, i: 1, t: 1 },
{ b: 2, i: 1, e: 1 },
{ b: 1, i: 1, k: 1, e: 1 },
{ b: 1, u: 1, n: 1, d: 1, l: 1, e: 1 }
]
这是棘手的部分:对于列表中的每个单词,我们检查它是否包含给定字符串中的每个字符,每个字符的数量相同或更高。如果是,
.every()
将返回 true
并且 .filter()
将在新列表中保留单词:
const output = list.filter(
(_, index) => charsAndAmount.every(
([char, number]) => number <= charMaps[index][char]
// [ 'b', 2] 2 <=
// ({ r: 1, a: 1, b: 2, i: 1, t: 1 })['b']
// 2 <= 2 === true
)
);
试试看:
function stringToMap(string) {
return [...string].reduce((map, char) => {
map[char] = map[char] + 1 || 1;
return map;
}, {});
}
const str = 'bib';
const charsAndAmount = Object.entries(stringToMap(str));
const list = ['rabbit', 'bibe', 'bike', 'bundle'];
const charMaps = list.map(stringToMap);
const output = list.filter(
(_, index) => charsAndAmount.every(
([char, number]) => number <= charMaps[index][char]
)
);
console.log(output);
Array.every()
方法简单地实现这一点,该方法测试数组中的所有元素是否通过提供的函数实现的测试。它返回一个Boolean
值。
现场演示:
let str = 'bib'
let list = ['rabbit','bibe','bundle']
for(let i = 0; i < list.length; i++) {
const allMatched = str.split('').every(e => list[i].indexOf(e) !== -1);
if (allMatched) {
console.log(list[i]);
}
}
根据作者评论更新答案:
let str = 'bib';
let list = ['rabbit','bibe','bundle'];
const res = list.map(e => {
return e.split('').filter(c => str.includes(c)).join('').length
});
res.forEach((matchedLength, index) => {
if (matchedLength >= 3) {
console.log(list[index])
}
})