Фильтрация свойства массива типов в массиве объектов с использованием другого массива

У меня есть массив объектов, которые нужно отфильтровать с помощью двух меню. Каждое меню возвращает массив. Значения этих массивов будут использоваться для фильтрации массива объектов.

Я создал пример codepen здесь: https://codepen.io/jonathank2018/pen/LYeZgQG?editors=1010

Для этого примера давайте сосредоточимся только на меню «Тузы». Логика фильтрации, которую я пытаюсь сделать, следующая. сценарий 1: когда я выбираю «Услуги» в меню «Тузы», значение «valuesAces» становится [«Услуги»]. сценарий 2: Когда я выбираю «Услуги» и «Подключено» в меню «Тузы», значение «valuesAces» становится [«Услуги», «Подключено»]. Когда я фильтрую «linksArray» со значениями, возвращаемыми из «valuesAces», мне нужно, чтобы результатом был массив со всеми объектами, которые имеют в своем свойстве aces хотя бы один из элементов в «valuesAces».

для сценария 1 я ожидаю, что в результате все объекты, которые имеют свойство aces ["Services"] как уникальное значение, и ["Services", "othervalues...", "othervalues..."].

scenario1 =  [ // services selected
                      { "src": "WayRay", "target": "AGP", "aces": [ "Services" ], "topic": [ "Map_Localisation" ] },
                      { "src": "Great_Wall", "target": "Audi", "aces": [ "Automated", " Connected", " Experience", " Services" ], "topic": [ "AP", " AVP", " Infrastructure" ] }, 
                      { "src": "Audi", "target": "BMW", "aces": [ "Automated", " Connected", " Experience", " Services" ], "topic": [ "AP", " AVP", " Infrastructure" ] },
                      { "src": "GM", "target": "Cruise", "aces": [ "Automated", " Services" ], "topic": [ "AV_Driverless" ] }, 
                      { "src": "Honda", "target": "Cruise", "aces": [ "Automated", " Services" ], "topic": [ "Parking" ] },
                      { "src": "Audi", "target": "Daimler", "aces": [ "Services", " Connected", " Experience" ], "topic": [ "AP", " AVP", " Infrastructure" ] },
                      { "src": "Xiaomi", "target": "Deepmotion", "aces": [ "Automated", " Services" ], "topic": [ "ADAS_uptoL2+", " AVP" ] },
                     ]

для сценария 2 я ожидаю, что в результате все объекты имеют свойство aces ["Services"] или ["Services", "othervalues...", "othervalues..."] или ["Connected"] или ["Службы", "Подключено","другие значения..."] или ["Подключено","другие значения..."].

 let scenario2 =    [ //services and connected selected
                      { "src": "WayRay", "target": "AGP", "aces": [ "Services" ], "topic": [ "Map_Localisation" ] },
                      { "src": "Great_Wall", "target": "Audi", "aces": [ "Automated", " Connected", " Experience", " Services" ], "topic": [ "AP", " AVP", " Infrastructure" ] }, 
                      { "src": "Audi", "target": "BMW", "aces": [ "Automated", " Connected", " Experience", " Services" ], "topic": [ "AP", " AVP", " Infrastructure" ] },
                      { "src": "Hesai", "target": "Black_Sesame", "aces": [ "Automated", " Connected" ], "topic": [ "AV_Driverless" ] }, 
                      { "src": "GM", "target": "Cruise", "aces": [ "Automated", " Services" ], "topic": [ "AV_Driverless" ] }, 
                      { "src": "Honda", "target": "Cruise", "aces": [ "Automated", " Services" ], "topic": [ "Parking" ] },
                      { "src": "Audi", "target": "Daimler", "aces": [ "Services", " Connected", " Experience" ], "topic": [ "AP", " AVP", " Infrastructure" ] },
                      { "src": "Xiaomi", "target": "Deepmotion", "aces": [ "Automated", " Services" ], "topic": [ "ADAS_uptoL2+", " AVP" ] },
                      { "src": "BMW", "target": "Deutsche_Telekom", "aces": [ "Connected" ], "topic": [ "E/E_Architecture" ] },  
                      ]

Если свойство aces объекта имеет хотя бы одно или несколько значений из valuesAces, то оно должно быть в результате фильтрации.

Проблема, с которой я сейчас сталкиваюсь в своем примере кода, заключается в том, что он не фильтрует так, как я этого хочу. Прямо сейчас, если я ссылаюсь на сценарий 2, в результате я нахожу только объекты, которые имеют в качестве свойства aces либо «Services», либо «Connected» в качестве первого элемента массива, но не объекты, которые имеют несколько элементов в свойстве aces и где «Сервисы» или «Подключено» не имеют индекса 0. Похоже, что все остальные элементы в массиве игнорируются, кроме первого.

Моя функция фильтрации выглядит так:

filteredLinks: function(){
      console.info("1")
          let result
          if (this.linksArray){
          if (
            (!this.valuesTopic || this.valuesTopic.length == 0)  // by topic
            && (!this.valuesAces || this.valuesAces.length == 0)  // by ACES
             ){
            console.info("2")
                result  = this.linksArray
          }else{
            console.info("3")
              result = this.linksArray.filter(link => { return (
                    ( !this.valuesTopic || this.valuesTopic.length == 0 || ([...link.topic].some(topic => this.valuesTopic.includes(topic)))) // by topic
                    &&( !this.valuesAces || this.valuesAces.length == 0 || ([...link.aces].some(ace => this.valuesAces.includes(ace)))) // by ACES
                    )})
          }
          return result;
          }
      },
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете отфильтровать массив linksArray, проверив, существуют ли элементы массива linksArray.aces в valuesAces следующим образом:

// Filter linksArray
linksArray.filter((item) => {
  return item.aces
    // 'aces' values in provided codepen has spaces so trim those.
    // If actual data doesn't have spaces, this map can be removed.
    .map((i) => {
      return i.trim()
    })
    // Check if 'acesValues' are in 'linksArray.aces' array
    .some((v) => {
      return valuesAces.includes(v)
    })
})

Или как один лайнер:

linksArray.filter((item) => item.aces.map((i) => i.trim()).some((v) => acesValues.includes(v)))

Вот пример:

let linksArray = [
  { src: 'SemiDrive', target: 'ADAYO', aces: ['Automated', ' Experience'], topic: ['EE_Architecture'] },
  { src: 'WayRay', target: 'AGP', aces: ['Services'], topic: ['Map_Localisation'] },
  { src: 'Hesai', target: 'Aiways', aces: ['Automated'], topic: ['Car_Access'] },
  { src: 'Oxbotica', target: 'AppliedEV', aces: ['Automated'], topic: ['Regulation'] },
  { src: 'Great_Wall', target: 'Audi', aces: ['Automated', ' Connected', ' Experience', ' Services'], topic: ['AP', ' AVP', ' Infrastructure'] },
  { src: 'Audi', target: 'BMW', aces: ['Automated', ' Connected', ' Experience', ' Services'], topic: ['AP', ' AVP', ' Infrastructure'] },
  { src: 'AEye', target: 'Benchmark', aces: ['Automated'], topic: [] },
  { src: 'Hesai', target: 'Black_Sesame', aces: ['Automated', ' Connected'], topic: ['AV_Driverless'] },
  { src: 'FAW', target: 'Cambricon', aces: ['Automated'], topic: ['AS_ADAS_uptoL2+'] },
  { src: 'GM', target: 'Cruise', aces: ['Automated', ' Services'], topic: ['AV_Driverless'] },
  { src: 'Honda', target: 'Cruise', aces: ['Automated', ' Services'], topic: ['Parking'] },
  { src: 'Audi', target: 'Daimler', aces: ['Services', ' Connected', ' Experience'], topic: ['AP', ' AVP', ' Infrastructure'] },
  { src: 'Xiaomi', target: 'Deepmotion', aces: ['Automated', ' Services'], topic: ['ADAS_uptoL2+', ' AVP'] },
  { src: 'Alibaba', target: 'Deeproute', aces: ['Automated'], topic: ['AD_Driverless'] },
  { src: 'BMW', target: 'Deutsche_Telekom', aces: ['Connected'], topic: ['E/E_Architecture'] }
]

let acesValues1 = ['Services']
let acesValues2 = ['Services', 'Connected']

const filterLinks = (links, aces) =>
  links.filter((item) => item.aces.map((i) => i.trim()).some((v) => aces.includes(v)))

console.info(filterLinks(linksArray, acesValues1))
console.info(filterLinks(linksArray, acesValues2))

РЕДАКТИРОВАТЬ

Основываясь на комментариях ОП, из значений linksArray.aces удалены начальные пробелы и добавлен фильтр тем:

let linksArray = [
  { src: 'SemiDrive', target: 'ADAYO', aces: ['Automated', 'Experience'], topic: ['EE_Architecture'] },
  { src: 'WayRay', target: 'AGP', aces: ['Services'], topic: ['Map_Localisation'] },
  { src: 'Hesai', target: 'Aiways', aces: ['Automated'], topic: ['Car_Access'] },
  { src: 'Oxbotica', target: 'AppliedEV', aces: ['Automated'], topic: ['Regulation'] },
  { src: 'Great_Wall', target: 'Audi', aces: ['Automated', 'Connected', 'Experience', 'Services'], topic: ['AP', ' AVP', ' Infrastructure'] },
  { src: 'Audi', target: 'BMW', aces: ['Automated', 'Connected', 'Experience', 'Services'], topic: ['AP', ' AVP', ' Infrastructure'] },
  { src: 'AEye', target: 'Benchmark', aces: ['Automated'], topic: [] },
  { src: 'Hesai', target: 'Black_Sesame', aces: ['Automated', 'Connected'], topic: ['AV_Driverless'] },
  { src: 'FAW', target: 'Cambricon', aces: ['Automated'], topic: ['AS_ADAS_uptoL2+'] },
  { src: 'GM', target: 'Cruise', aces: ['Automated', 'Services'], topic: ['AV_Driverless'] },
  { src: 'Honda', target: 'Cruise', aces: ['Automated', 'Services'], topic: ['Parking'] },
  { src: 'Audi', target: 'Daimler', aces: ['Services', 'Connected', 'Experience'], topic: ['AP', ' AVP', ' Infrastructure'] },
  { src: 'Xiaomi', target: 'Deepmotion', aces: ['Automated', 'Services'], topic: ['ADAS_uptoL2+', 'AVP'] },
  { src: 'Alibaba', target: 'Deeproute', aces: ['Automated'], topic: ['AD_Driverless'] },
  { src: 'BMW', target: 'Deutsche_Telekom', aces: ['Connected'], topic: ['E/E_Architecture'] }
]

let aces = ['Services']
let topics = ['ADAS_uptoL2+']

const filterLinks = (links, aces, topics) =>
  links
    .filter((item) => item.aces.some((v) => (aces.length ? aces.includes(v) : v)))
    .filter((item) => item.topic.some((v) => (topics.length ? topics.includes(v) : v)))

let result = filterLinks(linksArray, aces, topics)

console.info(result)

Более общий метод может выглядеть примерно так: const getFiltered = (column, values=[]) => linksArray.filter(lnkObj => lnkObj[column].some(el => values.includes(el.trim());. Теперь этот же метод можно использовать для topic. Я предполагаю, что следующим будет какой-то способ объединить оба (фильтр тузов и фильтр темы). :)

jsN00b 21.03.2022 18:06

@Tim, спасибо за подробный ответ. Применительно к одному из меню он работает по назначению. Теперь я хотел бы иметь возможность применять фильтры из обоих меню. Например, если я выбрал Services в меню Aces и ADAS_uptoL2+ в меню Topic, ожидаемый результат будет следующим: [ { "src": "Xiaomi", "target": "Deepmotion", "aces": [ "Automated ", "Сервисы" ], "тема": [ "ADAS_uptoL2+", "AVP" ] } ]

JK2018 21.03.2022 22:14

До сих пор я пробовал это: До сих пор я пробовал это: const filterLinks = this.linksArray.filter((item) => { return( item.topic.some((v) => this.valuesTopic.includes(v) ) )}) const filterLinks2 = this.filterLinks.filter((item) => { return( item.aces.some((v) => this.valuesAces.includes(v)) )}) result = filterLinks2

JK2018 21.03.2022 22:15

и это: const filterLinks = this.linksArray.filter((item) => { return( item.aces.some((v) => this.valuesAces.includes(v)) && item.topic.some((v) => this.valuesTopic.includes(v)) )}) result = filterLinks Но ни одна из них не работает, я не знаю, что я делаю неправильно..

JK2018 21.03.2022 22:17

Я забыл упомянуть, что я исправил пробелы, чтобы удалить map()

JK2018 21.03.2022 22:23

@ JK2018, пожалуйста, смотрите мое редактирование выше.

Tim 21.03.2022 23:11

@ Тим, чудесно! Работает как часы. Спасибо за качественную консультацию. Вы сделали мой день!

JK2018 22.03.2022 10:54

Другие вопросы по теме