Вывод должен быть только: 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.info(list[i])
}
}
}
Ожидаемый результат должен быть:
rabbit
bibe
Простым решением было бы подсчитать количество каждого уникального символа в заданной строке, а затем отфильтровать элементы на основе этого: если элемент содержит все эти символы, каждый с одинаковым или большим количеством, то его следует сохранить.
Во-первых, объявите вспомогательную функцию:
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.info(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.info(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.info(list[index])
}
})
@Scaplog Да, ты прав. Я как-то пропустил это. Спасибо что подметил это. Я посмотрю и поправлю логику.
@Scaplog Я добавил еще один фрагмент кода в соответствии с улучшением. Не могли бы вы взглянуть и проверить положительные и отрицательные сценарии и подтвердить.
Вот еще одно решение, если мы отсортируем буквы «нагрудник» станет «бби».
Если мы проделаем то же самое со списком ["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.info(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.info(JSON.stringify(result));
привет, спасибо за ваш ответ, но в нем все еще есть ошибка, если я запущу элемент, который содержит только «би», он все равно будет печатать пример, список массивов = ['rabit','bie','bundlei'] этот результат все равно напечатает, что не равно str = 'bib'