Выбор из массива объектов путем сопоставления свойства внутри, которое также является массивом - PullRequest
0 голосов
/ 24 октября 2019

Простите за заголовок, но в основном это то, что я пытаюсь сделать:

У меня есть массив объектов, давайте назовем их собаками для этого примера. Каждый объект выглядит примерно так:

    {
        name: "Poodle",
        keywords: ["Fluffy", "Intelligent", "Hypo-allergenic", "Loyal"]
    }

Пользователь выбирает три слова, а затем я хочу найти массив объектов и сопоставить эти три слова со свойством «ключевых слов» в каждом массиве. Тогда у меня есть некоторая логика отображения:

  • Если собака соответствует всем трем выбранным пользователем словам, я хочу вернуть только эту одну собаку.
  • Если есть только собаки, которыесовпадение по 2 словам, тогда я хочу взять максимум 2 таких собак.
  • Если есть только одна собака из 2 слов, а затем несколько матчей по 1 собаке, просто покажите собаку из 2 слов.
  • Если собачьи спички состоят только из одного слова, то покажите максимум три из них.

По сути, я не спрашиваю, как делать маркеры, я могу понять, чтовне, но в идеале мне нужно множество собак и количество матчей рядом с каждой. Затем я могу выполнить некоторую фильтрацию по этому вопросу.

Поэтому мне нужен массив имен собак , с общим количеством совпадений, что-то вроде этого (если, конечно, нет лучшего способа, чем явсе уши):

[
  ["Poodle", 2],
  ["Labrador", 2],
  ["Schpitz", 1],
  ["Setter", 0],
  ["Pit Bull", 0]
]

Похоже ли это на лучший подход или есть более простой / лучший способ?

Ответы [ 2 ]

1 голос
/ 24 октября 2019

Нет, это не похоже на лучший подход, потому что вы сохраняете что-то, что по сути является объектом в структуре массива. Лучшим подходом было бы сделать массив объектов результатов в качестве результата.

С помощью следующего фрагмента вы получите массив объектов, состоящий из имени собаки и всех подходящих ключевых слов.

Выиз него можно легко получить количество подходящих ключевых слов (используя result[i].matched.length), но я думаю, что это более практично, так как вы также можете показать, какие ключевые слова на самом деле соответствуют.

const data = [
  {
    name: "Poodle",
    keywords: ["Fluffy", "Intelligent", "Hypo-allergenic", "Loyal"]
  },
  {
    name: "Husky",
    keywords: ["Fluffy", "Cute", "Stuff", "IdkMuchAboutDogs"]
  }
];

const keywords = ["Fluffy", "Cute", "Intelligent"];

const result = data.map(dog => {
  return {
    dog: dog.name,
    matches: keywords.filter(keyword => dog.keywords.indexOf(keyword) !== -1)
  };
});

console.log(result);

Если вы хотите иметь больше логики при сравнении ключевых слов, вам нужно сделать что-то вроде

...
matches: keywords.filter(keyword => 
   dog.keywords.filter(dogkeyword => 
      // Now you can compare those two keywords with more complex algorithms
      dogkeyword.toLowerCase() == keyword.toLowerCase()
   ).length !== 0
)
...

или аналогичное.

0 голосов
/ 24 октября 2019

Вы можете создать счет по своему желанию:

let dogs = [
    {
        name: "Poodle",
        keywords: ["Fluffy", "Intelligent", "Hypo-allergenic", "Loyal"]
    },
    {
        name: "Dog2",
        keywords: ["Fluffy", "Intelligent", "Hypo-allergenic",]
    },
    {
        name: "Dog3",
        keywords: ["Fluffy"]
    }
]

Оценка:

let scored = words => dogs.map(dog => {
    // you can add modification for 2 words term
    let score = dog.keywords.filter(kw => words.includes(kw)).length

    return {
        name: dog.name,
        score
    }
})

А затем отсортировать по лучшему результату:

let sorted = dogs => dogs.sort((a,b) => b.score - a.score)
console.log(sorted(scored(['Fluffy', 'Loyal', "Intelligent"])))

{name: "Poodle", score: 3}
{name: "Dog2", score: 2}
{name: "Dog3", score: 1}

Это не такоптимально, но вы можете изменить его по ходу.

...