#javascript #jquery #arrays
#javascript #jquery #массивы
Вопрос:
var groupArray = [
['10', 'group one result', 'more result from group1'],
['10 20 30', 'group two result', 'another result from group two'],
['10 20 40', 'group three result']
];
function compare(entryArr, stringArr) {
for (var i in entryArr) {
str = stringArr.split(' '); //to array
ent = entryArr[i][0].split(' '); //first items of each group to array
if (str.every(s => ent.includes(s))) // compare
return entryArr[i].slice(1);
}
}
//find match from possible strings
console.log(compare(groupArray, '10')) // true
console.log(compare(groupArray, '10 20')) // true
console.log(compare(groupArray, '10 20 60')) // undefined. the result should come from group two
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Выше приведена структура моего проекта.
Мне нужно вернуть наиболее релевантный результат при сравнении массивов строк и записей.
Array.prototype.every()
Это самое близкое, что у меня есть для достижения моей цели после бесчисленных часов проб и ошибок…
Проблема показана в выводе # 3. Я понимаю Array.prototype.every()
, что вернет false, если элемент, который нужно найти, отсутствует в массиве, но должен быть обходной путь.
Если я удалю не похожие элементы в обоих массивах, я думал, что это решит проблему.
xyz = str.filter(x => ent.includes(x)) //output: ['10','20'] for sample #3
Я пытаюсь использовать xyz в качестве нового массива для строк, но тогда элемент в массиве ввода все равно будет присутствовать, поэтому вернет false .
Я могу получить разницу в обоих массивах…
entArr = str.filter(x => !ent.includes(x)) // entry array difference
strArr = ent.filter(x => !str.includes(x)) // string array difference
… но потом я застрял, пытаясь найти подходящее условие для применения.
Надеюсь, я хорошо объяснил это и спасибо за вашу помощь..
Ответ №1:
Вы могли бы использовать фильтр, чтобы найти все элементы, содержащие каждую строку, отслеживая количество и положение тех, которые делают, чтобы найти первый, который имеет наибольшее количество совпадений.
Что-то вроде:
var groupArray = [
['10', 'group one result'],
['10 20 30', 'group two result'],
['10 20 40', 'group three result']
];
function compare(entryArr, stringArr) {
let pos = 0;
let matches = 0;
for (var i in entryArr) {
str = stringArr.split(' ');
ent = entryArr[i][0].split(' ');
let f = str.filter(s => ent.includes(s));
if (f)
if (f.length > matches) {
pos = i;
matches = f.length;
}
}
if (matches > 0) {
return entryArr[pos].slice(1);
} else {
return [];
}
}
//find match from possible strings
console.log(compare(groupArray, '10')) // returns first entry that matches one value - group one result
console.log(compare(groupArray, '10 20')) // returns first entry that matches both values - group two result
console.log(compare(groupArray, '10 20 60')) // returns first entry with 2 matches - group two result
console.log(compare(groupArray, '50 60 80')) // no matches, returns empty array
** ОБНОВЛЕНИЕ: для возврата нескольких имен групп, в которых были найдены совпадения, упорядоченных по количеству совпадений, а затем по номерам групп **
var groupArray = [
['10', 'group one result', 'more one result'],
['10 20 40', 'group three result'],
['10 20 30', 'group two result'],
['10 20 30 40', 'group four result'],
['20 60', 'group five result']
];
function compare(entryArr, stringArr) {
// Array to hold ALL matches found
let matched = [];
// Loop through the entryArry array
for (let i = 0; i < entryArr.length; i ) {
// split search string into separate values
str = stringArr.split(' ');
// split the main array into separate values
ent = entryArr[i][0].split(' ');
// find any main array items that contain the search string values
let f = str.filter(s => ent.includes(s));
// If found...
if (f.length > 0) {
//... push into the matched array
matched.push([f.length, ...entryArr[i]]);
}
}
// If we have more than one match found, sort the matched array
// First by match count descending, then by the main array values, ascending
if (matched.length > 1) {
matched.sort(function(a, b){
if (a[0] == b[0]) {
return a[1] > b[1];
} else {
return a[0] < b[0];
}
})
// Now remove the unnecessary parts of each match
// We only want the group name, not the match count or the group's numbers string
for (let i = 0; i < matched.length; i ) {
matched[i] = matched[i].slice(2);
}
}
// return the result
return matched;
}
//find match from possible strings
console.log(compare(groupArray, '10'));
console.log(compare(groupArray, '10 20'));
console.log(compare(groupArray, '10 20 60'));
console.log(compare(groupArray, '20 30 40'));
Комментарии:
1. Спасибо, сэр! Я тестирую его в своем проекте, и пока он безупречен 🙂
2. np. Просто из любопытства, есть ли причина просто хотеть получить первый массив с наибольшим количеством совпадений? Все, что я делал и видел подобным образом, хотели бы получить как «два», так и «три» результата.
3. На самом деле я просто хотел отобразить массив с наиболее подходящим совпадением.. затем верните случайный элемент из группы, в которой он нашел совпадение. И вы решили мою проблему 🙂 еще раз спасибо!
4. ХОРОШО, np. На самом деле я только что обновил код. Функция «splice (1)» фактически удаляет часть массива, поэтому она исчезла навсегда. Я изменил эту часть, чтобы создать простой массив, используя вместо него только его содержимое —
[entryArr[pos][1]]
5. нет, ваш первый код в порядке. мы используем slice(1), поэтому он не будет возвращать первые элементы в каждой группе. Нам нужна только эта часть для хранения ключевых слов.