Фильтровать массив объектов на основе содержимого другого массива вложенных объектов

Я хочу отфильтровать массив positions и удалить все позиции, представленные в массиве people.

Я пробовал несколько комбинаций _.forEach и _.filter, но никак не могу понять.

console.info(position)

var test = _.filter(position, function(pos) {
    _.forEach(people, function(peo) {
        _.forEach(peo.position, function(peoplePos) {
            if (peoplePos.value == pos.value){
                return false;
            }
        });
    });
});

console.info(test)

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

var positions = [{
    val: 'CEO',
    label: 'CEO XXX'
}, {
    val: 'CTO',
    label: 'CTO XXX'
}, {
    val: 'CBO',
    label: 'CBO XXX'
}, {
    val: 'CLO',
    label: 'CLO XXX'
}]

var people = [{
    id: 'AAA',
    positions: [{
        val: 'CEO',
        label: 'CEO XXX'
    }]
},{
    id: 'BBB',
    positions: [{
        val: 'CXO',
        label: 'CXO XXX'
    },{
        val: 'CEO',
        label: 'CEO XXX'
    }]
},{
    id: 'CCC',
    positions: [{
        val: 'CTO',
        label: 'CTO XXX'
    }]
}]

В этом сценарии я стремлюсь к следующему результату:

var positions = [{
    val: 'CBO',
    label: 'CBO XXX'
}, {
    val: 'CLO',
    label: 'CLO XXX'
}]

Поскольку CBO и CLO не представлены никаким объектом в массиве людей.

Для пользователя с вашим представителем вы должны знать важность обмена усилиями

Rajesh 12.04.2019 15:25

@ Раджеш, да, извини за это. Одна минута

Daft 12.04.2019 15:26
.map() массив лиц, чтобы извлечь все массивы позиций, затем сгладить (или сгладить, а затем отобразить) результат, чтобы у вас был массив, содержащий все позиции, которые в настоящее время занимает хотя бы один человек. Затем просто .filter() массив позиций с помощью occupied_positions.includes( position ).
Shilly 12.04.2019 15:31

Вопрос @Rajesh обновлен. Просто пришлось нажать ctrl + z достаточно далеко до точки, где это имело смысл

Daft 12.04.2019 15:31

@Daft Pointer 1, у вас есть 2 forEach, но вы не возвращаетесь из внешнего forEach

Rajesh 12.04.2019 15:33
positions не position, а value не val. Обратному вызову filter нужен return, чтобы сделать что-то полезное, а _.forEach просто возвращает исходную коллекцию. Вы проверяли консоль при запуске?
trincot 12.04.2019 15:42
Поведение ключевого слова "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) для оценки ваших знаний,...
2
6
57
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Быстрый способ — преобразовать массив людей в строку и проверить позицию в строке.

Это избавит вас от необходимости зацикливаться на вложенной структуре.

var positions = [{ val: 'CEO', label: 'CEO XXX' }, { val: 'CTO', label: 'CTO XXX' }, { val: 'CBO', label: 'CBO XXX' }, { val: 'CLO', label: 'CLO XXX' }]

var people = [{ id: 'AAA', positions: [{ val: 'CEO', label: 'CEO XXX' }] }, { id: 'BBB', positions: [{ val: 'CXO', label: 'CXO XXX' }, { val: 'CEO',
    label: 'CEO XXX' }] }, { id: 'CCC', positions: [{ val: 'CTO', label: 'CTO XXX' }] }];

var stringifiedPeople = JSON.stringify(people)

var newPositions = positions.filter((position) =>
  !stringifiedPeople.includes(JSON.stringify(position))
);

console.info(newPositions)

Или вы можете создать карту, которая содержит все занятые позиции и отфильтровать доступные позиции.

var positions = [{ val: 'CEO', label: 'CEO XXX' }, { val: 'CTO', label: 'CTO XXX' }, { val: 'CBO', label: 'CBO XXX' }, { val: 'CLO', label: 'CLO XXX' }]

var people = [{ id: 'AAA', positions: [{ val: 'CEO', label: 'CEO XXX' }] }, { id: 'BBB', positions: [{ val: 'CXO', label: 'CXO XXX' }, { val: 'CEO',
    label: 'CEO XXX' }] }, { id: 'CCC', positions: [{ val: 'CTO', label: 'CTO XXX' }] }];

var mappedPositions = {}

people.forEach((p) =>
  p.positions.forEach((position) =>
    mappedPositions[position.val] = true
  )
);

var newPositions = positions.filter((position) => !mappedPositions[position.val]);

console.info(newPositions)

Картографическое решение отличное, очень ценю помощь. Пробовал нечто подобное, но не вышло. Спасибо еще раз!

Daft 12.04.2019 15:57

Вы можете использовать filter, find и some, чтобы отфильтровать те объекты, которые не отображаются в массиве position массива people.

var positions = [{val:'CEO',label:'CEOXXX'},{val:'CTO',label:'CTOXXX'},{val:'CBO',label:'CBOXXX'},{val:'CLO',label:'CLOXXX'}];
var people = [{id:'AAA',positions:[{val:'CEO',label:'CEOXXX'}]},{id:'BBB',positions:[{val:'CXO',label:'CXOXXX'},{val:'CEO',label:'CEOXXX'}]},{id:'CCC',positions:[{val:'CTO',label:'CTOXXX'}]}];

const out = positions.filter(position => {
  return !people.find(person => {
    return person.positions.some(({ val, label }) => {
      return val === position.val && label === position.label;
    });
  });
});

console.info(out);

Реализация моего комментария.

Все это можно записать в виде большого .reduce() в массиве позиций, чтобы сделать его более эффективным, но я предпочел показать точные шаги, чтобы было более понятно, что делает каждый шаг.

var positions = [{val:'CEO',label:'CEOXXX'},{val:'CTO',label:'CTOXXX'},{val:'CBO',label:'CBOXXX'},{val:'CLO',label:'CLOXXX'}];

var people = [{id:'AAA',positions:[{val:'CEO',label:'CEOXXX'}]},{id:'BBB',positions:[{val:'CXO',label:'CXOXXX'},{val:'CEO',label:'CEOXXX'}]},{id:'CCC',positions:[{val:'CTO',label:'CTOXXX'}]}];

const occupied_positions = people
  .map( person => person.positions )
  .flat()
  .map( position => position.val );
  
const all_positions = positions
  .map( position => position.val );
  
const open_positions = all_positions
  .filter( position => !occupied_positions.includes( position ))
  .map( position => positions.find( source => source.val === position ));
  
console.info( open_positions );

Просто указатель, вы должны использовать уменьшенную версию данных. Это позволяет сосредоточиться на вашем коде. Вы можете скопировать его из моего ответа или ответа Энди.

Rajesh 12.04.2019 15:49

Я использовал этот инструмент, потому что я ленив.

Andy 12.04.2019 15:51

Хорошая точка зрения. :) Поскольку у меня нет горизонтального колеса прокрутки, я ошибочно предположил, что люди ненавидят прокрутку вправо, чтобы иметь возможность читать ввод так же, как и я.

Shilly 12.04.2019 15:51

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