Рекурсивная модификация массива - PullRequest
0 голосов
/ 18 января 2020

Я хотел бы скопировать массив, чтобы не изменять оригинал, и удалить все выделенное: false из нового массива и вернуть этот новый массив. Массив бесконечно вложен, и с бесконечными именами свойств, которые не являются предсказуемыми, это должно быть возможно с помощью итерации, просматривая значение каждого свойства для Array.isArray (). Хотя я могу удалить объекты selected: false в итерации, я не могу вернуть измененный массив обратно в новый массив.

функция не может фильтровать инопланетян. Кроме того, функция работает в CodePen , но не в моем коде.

// sample nested data
var data = [
  {
    partyId: "animal-ID-001",
    selected: false,
    members: [
      {
        selected: false,
        userId: "animal-user-3443"
      },
      {
        selected: false,
        userId: "animal-user-3444"
      }
    ]
  },
  {
    partyId: "benjamin-ID-002",
    selected: true,
    members: [
      {
        selected: true,
        userId: "benjamin-user-5567",
        teams: [
          {
           selected: true,
           teamId: "team-benjamin-678"
          },
          {
            selected: false,
            teamId: "team-benjamin-3468"
          }
      ]},
      {
        selected: false,
        userId: "benjamin-user-55671"
      }
    ]
  },
  {
    partyId: "crystal-ID-003",
    selected: true,
    members: [
      {
        selected: true,
        userId: "crystal-user-8567"
      },
      {
        selected: true,
        userId: "crystal-user-85671"
      }
    ],
    aliens: [
      {
        selected: false,
        alienId: "crystal-alien-467"
      },
      {
        selected: false,
        alienId: "crystal-alien-230"
      }
    ]
  }
];

// remove selected false from array
// updated per suggestions

function updateState(arr) {
        return arr.filter(obj => obj.selected ).map( obj => {
            for (var prop in obj) {
                if( Array.isArray( obj[prop] ) ) {
                    return { ...obj, [prop]: updateState( obj[prop] ) };
                }
            }
            return { ...obj }
        });
    }

console.log( updateState( data ) );

Ответы [ 4 ]

1 голос
/ 20 января 2020

Работает ли что-то подобное для вас?:

const removeNonselected = (x) => 
  Array .isArray (x)
    ? x .reduce (
        (all, item) => item .selected === false 
          ? all 
          : all .concat (removeNonselected (item)), 
        []
      )
  : typeof x == 'object'
    ? Object .fromEntries (
        Object .entries (x) .map(([n, v]) => [n, removeNonselected(v)])
      ) 
  : x

const data = [{partyId: "animal-ID-001", selected: false, members: [{selected: false, userId: "animal-user-3443"}, {selected: false, userId: "animal-user-3444"}]}, {partyId: "benjamin-ID-002", selected: true, members: [{selected: true, userId: "benjamin-user-5567", teams: [{selected: true, teamId: "team-benjamin-678"}, {selected: false, teamId: "team-benjamin-3468"}]}, {selected: false, userId: "benjamin-user-55671"}]}, {partyId: "crystal-ID-003", selected: true, members: [{selected: true, userId: "crystal-user-8567"}, {selected: true, userId: "crystal-user-85671"}], aliens: [{selected: false, alienId: "crystal-alien-467"}, {selected: false, alienId: "crystal-alien-230"}]}];

console .log (removeNonselected (data))
console .log ('original data unchanged:')
console .log (data)

Это обрабатывает три случая: где данные являются массивом, где это объект или где-то еще. Для массива мы сохраняем только выбранные (где selected не false) и повторяем эти значения. Для объекта мы сохраняем другие значения без изменений, но возвращаемся к свойствам массива. Все остальное, что мы просто возвращаем как есть.

Это не удаляет свойство selected: false объекта, только из массива. Добавить это было бы не намного сложнее, но, похоже, это не соответствует вашим требованиям.

Если ваша среда не поддерживает Object.fromEntries, ее легко подобрать .

1 голос
/ 18 января 2020

Сначала .filter исходные данные, удаляя элементы с selected: false, затем .map результат и внутри обратного вызова, возвращают тот же объект, пока .filter использует свойство members. Тогда

var data = [{
    partyId: "animal-ID-001",
    selected: false,
    members: [{
        selected: false,
        userId: "animal-user-3443"
      },
      {
        selected: false,
        userId: "animal-user-3444"
      }
    ]
  },
  {
    partyId: "benjamin-ID-002",
    selected: true,
    members: [{
        selected: true,
        userId: "benjamin-user-5567"
      },
      {
        selected: false,
        userId: "benjamin-user-55671"
      }
    ]
  },
  {
    partyId: "crystal-ID-003",
    selected: true,
    members: [{
        selected: true,
        userId: "crystal-user-8567"
      },
      {
        selected: true,
        userId: "crystal-user-85671"
      }
    ]
  }
];
const updatedData = data
  .filter(({ selected }) => selected)
  .map(({ members, ...rest }) => ({
    ...rest,
    members: members.filter(({ selected }) => selected)
  }));
console.log(updatedData);
0 голосов
/ 18 января 2020

Не изобретайте велосипед, проверьте, какие функции вы можете использовать в массивах. Array.filter с рекурсией здесь идеально:

var data=[{partyId:"animal-ID-001",selected:!1,members:[{selected:!1,userId:"animal-user-3443"},{selected:!1,userId:"animal-user-3444"}]},{partyId:"benjamin-ID-002",selected:!0,members:[{selected:!0,userId:"benjamin-user-5567"},{selected:!1,userId:"benjamin-user-55671"}]},{partyId:"crystal-ID-003",selected:!0,members:[{selected:!0,userId:"crystal-user-8567"},{selected:!0,userId:"crystal-user-85671"}]}];

function removeNonselected(arr) {
  return arr.filter(obj => obj.selected).map(obj => {
    if(obj.members) return { ...obj, members: removeNonselected(obj.members) };
    else return { ...obj }
  });
}

console.log(removeNonselected(data));
0 голосов
/ 18 января 2020

Попробуйте это просто:

let selectedParties = data.filter(item => item.selected);
let partiesWithSelectedMembersOnly = selectedParties.map(item => {
  return {
    ...item,
    members: item.members.filter(member => member.selected)
  };
});

Array.filter () возвращает новый массив, поэтому вы не будете изменять исходный массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...