The problem is that you need to split each element of arr
in a word array. For example:
["frase qualquer", "uma qualquer aqui", "nada compatível"]
It has to be turned into:
[
["frase", "qualquer"],
["uma", "qualquer", "aqui"],
["nada", "compatível"]
]
So you can compare every word of this array of arrays individually.
As a first attempt, you can arrive at a solution more or less like this:
function mostCompatible(string, array) {
const words = string.split(' ');
// O `array` atualmente contém diversas strings.
// Fazendo o `map` abaixo, fazemos que cada string desse array
// seja dividida pelo espaço. Desse modo, teremos um array de arrays.
const subArrays = array.map((subString) => subString.split(' '));
// Na variável a seguir, vamos armazenar o índice referente
// ao elemento que tiver mais "palavras compatíveis", e o
// número de palavras compatíveis encontradas:
let current = {
index: null,
compatibleWordsCount: 0
};
// Agora vamos verificar qual elemento de `subArrays` tem
// mais "palavras compatíveis". Estou utilizando o `entries`
// como forma de obter o índice e o valor no laço `for..of`.
for (const [index, subArray] of subArrays.entries()) {
// Vamos obter a quantidade de "elementos compatíveis".
// Note que a seguinte computação possui complexidade `O(n^2)`.
const compatibleWordsCount = words.filter((word) => subArray.includes(word))
.length;
// Caso a quantidade de elementos compatíveis seja maior que o da iteração
// anterior, vamos sobrescrever o objeto `current`.
if (compatibleWordsCount > current.compatibleWordsCount) {
current = { index, compatibleWordsCount };
}
}
// Retornar o elemento de `array` correspondente ao índice do `subArray` com
// mais "elementos compatíveis" encontrados.
return array[current.index];
}
console.log(
mostCompatible('uma frase qualquer aqui', [
'frase qualquer',
'uma qualquer aqui',
'nada compatível'
])
); // Deve logar `'uma qualquer aqui'`.
The problem is that it is not very performative, having complexity of approximately O(n3), since we are using a includes
within a filter
, that is inside a for
, and each of these steps has complexity O(n). But frankly, you only need to take this into account if you are going to take a significant number of data to that function.
A slightly more efficient implementation could make use of a map to perform the searches. Thus, you reduce the complexity of each search from O(n) to O(1). Something like this:
function createCountMap(arr) {
const map = Object.create(null);
for (const item of arr) {
map[item] = (map[item] || 0) + 1;
}
return map;
}
function mostCompatible(string, array) {
// Criamos um mapa com cada palavra a ser procurda.
// Assim, a busca terá complexidade O(1) ao invés de O(n).
const wordsMap = createCountMap(string.split(' '));
let result = {
index: null,
compatibleWordsCount: 0
};
for (let index = 0; index < array.length; index++) {
const currentString = array[index];
let compatibleWordsCount = 0;
for (const word of currentString.split(' ')) {
if (wordsMap[word]) {
compatibleWordsCount++;
}
}
if (compatibleWordsCount > result.compatibleWordsCount) {
result = { index, compatibleWordsCount };
}
}
return array[result.index];
}
console.log(
mostCompatible('uma frase qualquer aqui', [
'frase qualquer',
'uma qualquer aqui',
'nada compatível'
])
); // Deve logar `'uma qualquer aqui'`.
To learn more about this notation - O(n) - I used, read here.
But if the array you are looking for is fixed, you can save the result of
map
and it will only be used once, or even no– Costamilam