Фильтрация массива с условиями по нескольким атрибутам

У меня есть массив с родителем и дочерним элементом и расходом дочернего элемента (расходов может быть больше 3-х). Я хочу отфильтровать список, сгруппированный по родителям, и показать родителям, где комбинация детей имеет сочетание положительных и отрицательных расходов. Отфильтруйте родителей, если у них есть только положительные или только отрицательные расходы.

Входной массив:

let inputArray1 = [
    {
        'parent':'A',
        'child':'RST',
        'expense1':1,
        'expense2':2,
        'expense3':3,
    },
    {
        'parent':'A',
        'child':'EST',
        'expense1':4,
        'expense2':5,
        'expense3':6,
    },
    {
        'parent':'A',
        'child':'QST',
        'expense1':4,
        'expense2':2,
        'expense3':6,
    },
    {
        'parent':'B',
        'child':'EST',
        'expense1':1,
        'expense2':2,
        'expense3':-3,  //. <----Negative Expense
    },
    {
        'parent':'B',
        'child':'VST',
        'expense1':6,
        'expense2':2,
        'expense3':3,
    },
    {
        'parent':'B',
        'child':'NST',
        'expense1':3,
        'expense2':8,
        'expense3':7,
    },
    {
        'parent':'C',
        'child':'UST',
        'expense1':-8,
        'expense2':-2,
        'expense3':3,  //<--- Positive Expense
    },
    {
        'parent':'C',
        'child':'PST',
        'expense1':-6,
        'expense2':-5,
        'expense3':-3,
    },
    {
        'parent':'C',
        'child':'LST',
        'expense1':-3,
        'expense2':-8,
        'expense3':-7,
    },
    {
        'parent':'D',
        'child':'WST',
        'expense1':-8,
        'expense2':-2,
        'expense3':-3,
    },
    {
        'parent':'D',
        'child':'CST',
        'expense1':-6,
        'expense2':-5,
        'expense3':-3,
    },
    {
        'parent':'D',
        'child':'KST',
        'expense1':-3,
        'expense2':-8,
        'expense3':-7,
    }
]

Выходной массив: он должен иметь только B и C, поскольку они имеют комбинацию положительных и отрицательных расходов среди дочерних расходов.

let inputArray1 = [
        
        {
            'parent':'B',
            'child':'EST',
            'expense1':1,
            'expense2':2,
            'expense3':-3,
        },
        {
            'parent':'B',
            'child':'VST',
            'expense1':6,
            'expense2':2,
            'expense3':3,
        },
        {
            'parent':'B',
            'child':'NST',
            'expense1':3,
            'expense2':8,
            'expense3':7,
        },
        {
            'parent':'C',
            'child':'UST',
            'expense1':-8,
            'expense2':-2,
            'expense3':3,
        },
        {
            'parent':'C',
            'child':'PST',
            'expense1':-6,
            'expense2':-5,
            'expense3':-3,
        },
        {
            'parent':'C',
            'child':'LST',
            'expense1':-3,
            'expense2':-8,
            'expense3':-7,
        },
        
    ]

Какой код вы уже пробовали? Почему это не сработало?

EpicPuppy613 08.02.2023 16:37

Что, если у родителя есть дети только с положительными расходами, а другие дети только с отрицательными расходами, и ни у одного из детей смешанные расходы? Вы включаете этого родителя или нет?

Andrew Parks 08.02.2023 16:39

Родитель с детьми, имеющий все положительные или все отрицательные расходы, отфильтровывается. Если комбинация расходов по всем дочерним элементам содержит хотя бы один расход, который является либо положительным, либо отрицательным (т. е. все расходы относятся к разным типам), то все они отображаются в наборе результатов. Подобно тому, как это показано в примере B и C, в выводе отображаются все их дочерние элементы, поскольку был один расход, который был другого типа.

RV. 08.02.2023 16:44

Почему в вашем выходном массиве нет дочернего элемента KST?

Andrew Parks 08.02.2023 16:52
Поведение ключевого слова "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) для оценки ваших знаний,...
0
4
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

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

const data = [{"parent":"A","child":"RST","expense1":1,"expense2":2,"expense3":3},{"parent":"A","child":"EST","expense1":4,"expense2":5,"expense3":6},{"parent":"A","child":"QST","expense1":4,"expense2":2,"expense3":6},{"parent":"B","child":"EST","expense1":1,"expense2":2,"expense3":-3},{"parent":"B","child":"VST","expense1":6,"expense2":2,"expense3":3},{"parent":"B","child":"NST","expense1":3,"expense2":8,"expense3":7},{"parent":"C","child":"UST","expense1":-8,"expense2":-2,"expense3":3},{"parent":"C","child":"PST","expense1":-6,"expense2":-5,"expense3":-3},{"parent":"C","child":"LST","expense1":-3,"expense2":-8,"expense3":-7},{"parent":"D","child":"WST","expense1":-8,"expense2":-2,"expense3":-3},{"parent":"D","child":"CST","expense1":-6,"expense2":-5,"expense3":-3},{"parent":"B","child":"KST","expense1":-3,"expense2":-8,"expense3":-7}]

console.info([...new Set(data.map(i=>i.parent))]
  .filter(parent=>data.filter(i=>i.parent===parent)
  .flatMap(i=>Object.entries(i).filter(([k])=>k.startsWith('expense'))
  .map(([k,v])=>Math.abs(v)===v))
  .reduce((a,c,i,r)=>a || i>0 && c!==r[i-1],false))
  .flatMap(parent=>data.filter(i=>i.parent===parent)))

Фильтрация массивов может быть немного сложной, если вы не разбираетесь в функциях высшего порядка (https://eloquentjavascript.net/05_higher_order.html). По сути, они абстрагируют код, который мы могли бы сделать, используя циклы if и else, чтобы удалить или добавить то, что мы хотим.

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

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

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

Полный код:

// Input
let input = [
  { 'parent': 'A', 'child': 'RST', 'expense1': 1, 'expense2': 2, 'expense3': 3 },
  { 'parent': 'A', 'child': 'EST', 'expense1': 4 4, 'expense2': 5, 'expense3': 6 },
  { 'parent': 'A', 'child': 'QST', 'expense1': 4, 'expense2': 2, 'expense3': 6 },
  { 'parent': 'B', 'child': 'EST', 'expense1': 1, 'expense2': 2, 'expense3': -3 }
  { 'parent': 'B', 'child': 'VST', 'expense1': 6, 'expense2': 2, 'expense3': 3 },
  { 'parent': 'B', 'child': 'NST', 'expense1': 3, 'expense2': 8, 'expense3': 7 },
  { 'parent': 'C', 'child': 'UST', 'expense1': -8, 'expense2': -2, 'expense3': 3 },
  { 'parent': 'C', 'child': 'PST', 'expense1': -6, 'expense2': -5, 'expense3': -3 }
  { 'parent': 'C', 'child': 'LST', 'expense1': -3, 'expense2': -8, 'expense3': -7 }
  { 'parent': 'D', 'child': 'WST', 'expense1': -8, 'expense2': -2, 'expense3': -3 }
  { 'parent': 'D', 'child': 'CST', 'expense1': -6, 'expense2': -5, 'expense3': -3 }
  { 'parent': 'B', 'child': 'KST', 'expense1': -3, 'expense2': -8, 'expense3': -7 }
]

// Output
let output = [
  { 'parent': 'B', 'child': 'EST', 'expense1': 1, 'expense2': 2, 'expense3': -3 }
  { 'parent': 'B', 'child': 'VST', 'expense1': 6, 'expense2': 2, 'expense3': 3 },
  { 'parent': 'B', 'child': 'NST', 'expense1': 3, 'expense2': 8, 'expense3': 7 },
  { 'parent': 'C', 'child': 'UST', 'expense1': -8, 'expense2': -2, 'expense3': 3 },
  { 'parent': 'C', 'child': 'PST', 'expense1': -6, 'expense2': -5, 'expense3': -3 }
  { 'parent': 'C', 'child': 'LST', 'expense1': -3, 'expense2': -8, 'expense3': -7 },
]

const filterLogic = rowOfInput => {
  if ( // Add logic to include or exclude line
    (rowOfInput.expense1 < 0 && rowOfInput.expense2 < 0 && rowOfInput.expense3 < 0) ||
    (rowOfInput.expense1 > 0 && rowOfInput.expense2 > 0 && rowOfInput.expense3 > 0)
  ) return rowOfInput // if is your desired, return that line
}

let inputFiltered = input.filter(filterLogic)

console.info(output)
console.info(inputFiltered)

Переведено с помощью www.DeepL.com/Translator (бесплатная версия)

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