【问题标题】:Recursive Array Modification递归数组修改
【发布时间】:2020-05-04 20:14:13
【问题描述】:

我想复制一个数组以免修改原始数组,并从新数组中删除所有 selected: false ,并返回这个新数组。该数组是无限嵌套的,并且具有不可预测的无限属性名称,因此这应该可以通过迭代查看 Array.isArray() 的每个属性的值来实现。虽然我可以在迭代中删除 selected:false 对象,但我无法将修改后的数组返回到新数组。

函数无法过滤外星人。此外,函数在 in 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 ) );

【问题讨论】:

  • updateState( obj[prop] ) 是做什么的?
  • var arr = [...originalArr]; 是浅拷贝。使用 lodash 它有 deepClone 功能,但如果你坚持不使用外部库,你也可以这样做:arr = JSON.parse(JSON.stringify(data)) 但请务必先阅读:medium.com/@pmzubar/…

标签: javascript arrays recursion nested


【解决方案1】:

首先.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);

【讨论】:

    【解决方案2】:

    试试这个简单的:

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

    Array.filter() 返回一个新的数组,所以你不会修改初始的。

    【讨论】:

      【解决方案3】:

      不要重新发明轮子,检查可以在数组上使用哪些函数。 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));

      【讨论】:

      • @Klaycom 谢谢。这些回复的唯一问题是您将“成员”作为一种财产,而有无限的。也许我需要更清楚地说明这一点。我会尝试调整这些响应。
      【解决方案4】:

      这样的事情对你有用吗?:

      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 属性,只会从数组中删除。添加它并不难,但它似乎不在您的要求中。

      如果您使用doesn't support Object.fromEntries 环境,那么填充相当容易。

      【讨论】:

        猜你喜欢
        • 2018-07-06
        • 1970-01-01
        • 2020-09-11
        • 2016-01-22
        • 2011-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多