打印包含给定单词所有字符的列表项

问题描述 投票:0回答:3

输出应该只有:rabbit 和 bibe 但我弄错了列表中的所有内容都在打印,因为最后一个索引也有'b'以及我如何打印仅包含'bib'的指定元素

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
javascript arrays performance
3个回答
1
投票

这是另一个解决方案,如果我们将字母“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));


1
投票

一个简单的解决方案是计算给定字符串中每个唯一字符的数量,然后基于此过滤元素:如果一个元素具有所有这些字符,每个字符的数量相同或更高,那么它应该被保留。

首先,声明一个辅助函数:

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);


1
投票

您可以借助

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])
  }
})

© www.soinside.com 2019 - 2024. All rights reserved.