Есть ли лучший способ проверить сходство в массиве? - PullRequest
0 голосов
/ 09 мая 2019

Я получаю ответ, который возвращает, и массив хэшей. Массив хэшей имеет два ключа «заголовок» и «абзац». Иногда я получаю ответы, которые возвращают похожие значения в ключе абзаца.

Например, когда я просто возвращаю значения в абзаце:

["Welcome to the best place", "Welcome to the best place in the world, Boston!"]

Вы видите, что в индексе 0 он включает в себя то, что в индексе 1

Я сопоставляю массив хэшей, чтобы вернуть один из ключей «абзац». Затем я пытаюсь отфильтровать первый элемент, если значение равно любому из других элементов в массиве. У меня есть кое-что, что работает только тогда, когда массив имеет значения, подобные состоянию выше и вернет пустой массив в случае сбоя.

const description = hotel
    .description()
    .map(descriptions => descriptions.paragraph)
    .filter((paragraph, index) => !paragraph[index].includes(paragraph[0]))

Где hotel.description() возвращает массив хэшей, а цепочка карт для фильтрации возвращает результаты в массиве

Приведенный выше пример кода возвращает правильный ответ, где массив:

["Welcome to the best place", "Welcome to the best place in the world, Boston!"]

становится:

["Welcome to the best place in the world, Boston!"]

Но если возвращаемый массив уникален, возвращается пустой массив.

Ожидаемые результаты:

["You are here at the best place", "Welcome to the best place in the world, Boston!"]

Фактические результаты: []

Не уверен, что еще нужно добавить в эту цепочку, чтобы она возвращала уникальные значения.

Ответы [ 3 ]

2 голосов
/ 09 мая 2019

Я упрощаю ваш пример для работы с ним, но концепция все еще применяется здесь.Я также делаю следующие предположения:

  • «Аналог» означает «включает»
  • Вас заинтересует все сходство, а не только сходство с первым
  • Ваши исходные данные не имеют строгих дублирующих фраз (хотя это можно обойти)
  • Вы предпочитаете удалять подмножества фраз и сохранять надстрочные фразы (если это имеет смысл).

Если так, то следующий подход, кажется, работает для ваших нужд:

let greetings = [
  "Welcome to the best place", 
  "Welcome to the best place in the world, Boston!"
];

let condensed = 
  greetings
  .filter(g => 
    !greetings.some(other => other.includes(g) && !(other == g))
  );

console.log(condensed);

И здесь он не возвращает пустой массив, когда все значения не похожи:

let greetings = [
  "You're at the best place", 
  "Welcome to the best place in the world, Boston!"
];

let condensed = 
  greetings
  .filter(g => 
    !greetings.some(other => other.includes(g) && !(other == g))
  );

console.log(condensed);
1 голос
/ 09 мая 2019

Это одна возможность.Я выделяю обнаружение сходства и выбор лучшего из двух одинаковых предметов из логики сохранения сходных.Функция includes просто сообщает, является ли одна из двух строк подстрокой другой, а longer выбирает более длинную из двух строк.

Очевидно, что эти вспомогательные функции могут быть встроены обратно в основную функцию, ноЯ думаю, что это более логично.

const keepSimilar = (similarTo, better) => (xs) => 
  xs.reduce((found, x) => {
    const index = found.findIndex(similarTo(x))
    if (index > -1) {
      found[index] = better(x, found[index])
    } else {
      found.push(x)
    }
    return found
  }, [], xs)

const includes = (s1) => (s2) => s1.includes(s2) || s2.includes(s1)
const longer = (s1, s2) => s2.length > s1.length ? s2 : s1 

const similarParas = keepSimilar(includes, longer)

const paras = ['foo', 'bar', 'baz', 'foobar', 'bazqux']

console.log(similarParas(paras)) //=> ['foobar', 'baz', 'barqux']
console.log(similarParas(['ABC', 'AB', 'DEF', 'DEFG'])) //=> ['ABC','DEFG']
console.log(similarParas([
  'Welcome to the best place', 
  'Welcome to the best place in the world, Boston!'
]))
//=> ['Welcome to the best place in the world, Boston!']

console.log(similarParas([
  'You are here at the best place', 
  'Welcome to the best place in the world, Boston!'
]))
//=> ['You are here at the best place', 'Welcome to the best place in the world, Boston!']

Это не очень красивый код.Я являюсь одним из принципов Рамды , и я бы сделал это совсем по-другому с такой библиотекой, особенно избегая мутации объекта-аккумулятора.Но это должно сработать.

0 голосов
/ 10 мая 2019

Вот как вы делаете это за один раз, используя уменьшите понимание массива:

const result =
        [{ paragraph: "D" }, { paragraph: "A" }, { paragraph: "ABC" }, { paragraph: "AB" }, { paragraph: "A" }, { paragraph: "DEFG" }, { paragraph: "DE" }]
            .map(({ paragraph }) => paragraph)
            .sort()
            .reverse()
            .reduce((existingParagraphs, currentParagraph) => {

                if (existingParagraphs.length == 0
                    || !existingParagraphs.some(existingParagraph => existingParagraph.startsWith(currentParagraph))) {
                    existingParagraphs.push(currentParagraph);
                }
                return existingParagraphs;
            }, []);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...