Отфильтровать список в списке и сохранить структуру

Предполагая, что у меня есть этот список

const foo = [
  {
    id: 1,
    bar: [ {id: 1, a: null}, {id: 2, a: 224}, {id: 3, a: 345}, ]
  },
  {
    id: 2,
    bar: [ {id: 4, a: 763}, {id: 5, a: null}, {id: 3, a: 111}, ]
  }
]

Как отфильтровать список, чтобы все a: null удалялись, но структура списка оставалась прежней?

Я старался

foo.map(elem => elem.bar.filter(bar => bar.a !== null))

но это дает мне.

foo = [
    [{id: 2, a: 224}, {id: 3, a: 345}, ],
    [ {id: 4, a: 763}, {id: 3, a: 111}, ]
]

Я хочу, чтобы вывод был

foo = [
  {
    id: 1,
    bar: [ {id: 2, a: 224}, {id: 3, a: 345}, ]
  },
  {
    id: 2,
    bar: [ {id: 4, a: 763}, {id: 3, a: 111}, ]
  }
]

Пожалуйста, добавьте ожидаемый результат. Вы хотите отфильтровать свойство bar или весь массив.

Maheer Ali 22.05.2019 16:51

@MaheerAli добавил это

Stophface 22.05.2019 16:52
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
2
2
45
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Внешний метод должен быть map() вместо filter().

const foo = [
  {
    id: 1,
    bar: [ {id: 1, a: null}, {id: 2, a: 224}, {id: 3, a: 345}, ]
  },
  {
    id: 2,
    bar: [ {id: 4, a: 763}, {id: 5, a: null}, {id: 3, a: 111}, ]
  }
]

const res = foo.map(elem => ({...elem,bar:elem.bar.filter(bar => bar.a !== null)}))
console.log(res)

Вот что я бы сделал! Красиво и чисто

Amin Jafari 22.05.2019 17:12

Я бы с удовольствием, но я не ОП :)

Amin Jafari 22.05.2019 17:22
Ответ принят как подходящий

Если вы согласны с изменением массива, вы можете обновить bar отфильтрованными объектами:

const foo = [{id:1,bar:[{id:1,a:null},{id:2,a:224},{id:3,a:345},]},{id:2,bar:[{id:4,a:763},{id:5,a:null},{id:3,a:111},]}]

foo.forEach(o => o.bar = o.bar.filter(obj => obj.a !== null))

console.log(foo)

Если вам нужен новый массив, вы можете использовать map

const foo = [{id:1,bar:[{id:1,a:null},{id:2,a:224},{id:3,a:345},]},{id:2,bar:[{id:4,a:763},{id:5,a:null},{id:3,a:111},]}]

const newArray = foo.map(o => ({ ...o, bar: o.bar.filter(obj => obj.a !== null) }))

console.log(newArray)

Поскольку вы на самом деле фильтруете только внутренний массив, вы хотите использовать map для внешнего массива.

const original = [
  {
    id: 1,
    bar: [ {id: 1, a: null}, {id: 2, a: 224}, {id: 3, a: 345}, ]
  },
  {
    id: 2,
    bar: [ {id: 4, a: 763}, {id: 5, a: null}, {id: 3, a: 111}, ]
  }
]

const result = original.map(elem => ({...elem, bar: elem.bar.filter(bar => bar.a !== null)}));

console.log(`result: ${JSON.stringify(result, null, 2)}`);


// Note: original array unchanged
console.log(`original (unchanged): ${JSON.stringify(original, null, 2)}`);

Нет смысла использовать map, если вы мутируете исходный массив

adiga 22.05.2019 16:59
elem.bar = elem.bar.filter... мутирует объекты в foo. Это можно сделать всего лишь foo.forEach(o => o.bar = ... Все это не имеет значения, когда вы переназначаете foo
adiga 22.05.2019 17:05

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

Amin Jafari 22.05.2019 17:06

На самом деле, хороший улов, это мутация оригинала. С тех пор я обновил его.

Tim Klein 22.05.2019 17:10

Вы можете использовать фильтр после доступа к каждому другому объекту сначала с помощью .forEach()

const foo = [
  {
    id: 1,
    bar: [ {id: 1, a: null}, {id: 2, a: 224}, {id: 3, a: 345}, ]
  },
  {
    id: 2,
    bar: [ {id: 4, a: 763}, {id: 5, a: null}, {id: 3, a: 111}, ]
  }
]

foo.forEach(obj => obj.bar = obj.bar.filter(subObj => subObj.a != null))

console.log(foo)

Если вы не хотите изменять массив, вы можете использовать JSON.parse(JSON.stringify(obj)) для его клонирования:

var foo = [
  {
    id: 1,
    bar: [ {id: 1, a: null}, {id: 2, a: 224}, {id: 3, a: 345}, ]
  },
  {
    id: 2,
    bar: [ {id: 4, a: 763}, {id: 5, a: null}, {id: 3, a: 111}, ]
  }
]
var newFoo = JSON.parse(JSON.stringify(foo))
newFoo.forEach(obj => obj.bar = obj.bar.filter(subObj => subObj.a != null))

console.log('Original:\n', foo)
console.log('New Array:\n', newFoo)

Ха-ха, да ладно, мало что можно сделать. Вы получаете тех, кто просто хочет, чтобы их ответ был наверху: p Как вы сказали, они даже не говорят, почему они проголосовали против. Если бы они это сделали, я мог бы переписать свой ответ, что принесет пользу человеку и сообществу.

Kobe 22.05.2019 17:03

@AminJafari Я не минусовал, но объяснять минусы никогда не бывает хорошей идеей. Это приводит к войнам комментариев и мести

adiga 22.05.2019 17:07

@adiga, не объясняющий отрицательный голос, обескураживает отвечающего и может привести к тому, что он больше не будет отвечать на вопросы и не приложит никаких усилий к SO в целом. Кроме того, некоторые люди используют систему голосования больше как кнопку «нравится / не нравится», хотя ответ правильный, как в этом случае.

Amin Jafari 22.05.2019 17:11

@adiga Я согласен с вами обоими, но мне наплевать на представителя. Если кому-то не нравится мой ответ, пусть будет так, но если он неправильный, объяснение мне, почему он неправильный, помогает мне и сообществу учиться.

Kobe 22.05.2019 17:13

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