【问题标题】:filtering deep nested objects array using lodash not working correctly使用 lodash 过滤深层嵌套对象数组无法正常工作
【发布时间】:2018-03-26 11:39:31
【问题描述】:

我的产品结构如下图:

   product = {  
  "name":"MyXam",
  "layers":[  
    {  
      "countries":[  
        {  
          "countryId":"1",
          "countryName":"ABC"
        },
        {  
          "countryId":"2",
          "countryName":"XYZ"
        },
        {  
          "countryId":"3",
          "countryName":"PQR"
        }
      ]
    },
    {  
      "countries":[  
        {  
          "countryId":"5",
          "countryName":"LMN"
        },
        {  
          "countryId":"3",
          "countryName":"PQR"
        }
      ]
    }
  ]
}

以及选定的国家/地区:

selCountries =    [  
  {  
    "countryId":"1"
  },
  {  
    "countryId":"3"
  }
]

现在我想过滤product,使其只包含countries 中的selCountries

最终产品应该是:

{  
  "name":"MyXam",
  "layers":[  
    {  
      "countries":[  
        {  
          "countryId":"1",
          "countryName":"ABC"
        },
        {  
          "countryId":"3",
          "countryName":"PQR"
        }
      ]
    },
    {  
      "countries":[  
        {  
          "countryId":"3",
          "countryName":"PQR"
        }
      ]
    }
  ]
}

我已尝试使用 lodash 进行以下操作,但无法正常工作:

_.filter(product.layers, _.flow(
      _.property('countries'),
      _.partialRight(_.some, selCountries)
  ));

product 在我的应用程序中动态出现。在某些情况下,某些layers 可能没有countries。所以解决方案也应该处理这种情况,并且不应该因未定义的错误而中断。

谁能帮帮我,我哪里出错了?

【问题讨论】:

    标签: javascript underscore.js lodash


    【解决方案1】:

    你不应该为此需要 lodash。只需filter 基于 ID。如果对于所有图层,请在图层上映射/forEach 并过滤国家/地区。

    const product = {  
      "name":"MyXam",
      "layers":[  
        {  
          "countries":[  
            {  
              "countryId":"1",
              "countryName":"ABC"
            },
            {  
              "countryId":"2",
              "countryName":"XYZ"
            },
            {  
              "countryId":"3",
              "countryName":"PQR"
            }
          ]
        }
      ]
    }
    
    const selCountries = [  
      {  
        "countryId":"1"
      },
      {  
        "countryId":"3"
      }
    ];
    
    const indices = selCountries.map(e => e.countryId); // Just IDs plz.
    product.layers.forEach(layer => {
       if (layer.countries == null)
           return;
    
       layer.countries = layer.countries.filter(e => 
           indices.some(i => i == e.countryId)
       );
    });
    console.log(product);

    【讨论】:

    • 在我的应用程序中,产品是动态的,在某些情况下,图层可能也没有国家/地区,在这种情况下,它会抛出错误,说未定义过滤器。在您的解决方案中是否有任何简单的方法来处理这个问题
    • @MadasuK:可能会在过滤之前添加一个空检查。将代码更改为 forEach(就地修改图层!)。但是您不想等待产品加载吗?
    • 即使服务器端响应有时也缺少该国家/地区属性。
    • 如果没有结果,我可能只是将属性设置为一个空数组。
    【解决方案2】:

    我的答案与 31piy 的类似,因为我先从 selCountries 中提取 id,然后使用过滤后的结果重建对象。它还会根据您最近的评论检查图层数组中是否有国家/地区。

    product = {"name":"MyXam","layers":[{"countries":[{"countryId":"1","countryName":"ABC"},{"countryId":"2","countryName":"XYZ"},{"countryId":"3","countryName":"PQR"}]},{"countries":[{"countryId":"5","countryName":"LMN"},{"countryId":"3","countryName":"PQR"}]}]}
    const selCountries=[{"countryId":"1"},{"countryId":"3"}];
    
    if (product.layers.length) {
      const selCountriesArr = selCountries.map(el => el.countryId);
      const newLayers = product.layers.map(obj => {
        const countries = obj.countries.filter(el => selCountriesArr.includes(el.countryId));
        return { countries };
      });
      const filteredProduct = { ...product, layers: newLayers };
      console.log(filteredProduct);
    }

    【讨论】:

    • Andy,它应该适用于所有不在索引 0 的层,就像在您的解决方案 product.layers[0] 中一样。我们可以让它通用吗?
    • 好吧,我只能根据你问题中的细节来回答。也许您可以用这些新信息更新您的问题,以便我理解。
    【解决方案3】:

    您可以使用所选国家/地区的 ID 创建一个临时数组,然后根据它过滤国家/地区。请注意,它会就地修改原始对象。

    let product = {
      "name": "MyXam",
      "layers": [{
        "countries": [{
            "countryId": "1",
            "countryName": "ABC"
          },
          {
            "countryId": "2",
            "countryName": "XYZ"
          },
          {
            "countryId": "3",
            "countryName": "PQR"
          }
        ]
      }]
    };
    
    let selCountries = [{
        "countryId": "1"
      },
      {
        "countryId": "3"
      }
    ];
    
    // Extract the IDs
    let selCountryIds = _.map(selCountries, 'countryId');
    
    // Filter the countries based on IDs
    product.layers[0].countries = _.filter(product.layers[0].countries, country => {
      return _.includes(selCountryIds, country.countryId);
    });
    
    console.log(product);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

    【讨论】:

    • 它应该适用于所有层,而不仅仅是在解决方案 product.layers[0] 中给出的索引 0 处
    【解决方案4】:

    您可以使用Array.mapArray.filter 来遍历数组并根据selected countries. 过滤product,而不是使用lodash

    var product = {  
      "name":"MyXam",
      "layers":[  
        {  
          "countries":[  
            {  
              "countryId":"1",
              "countryName":"ABC"
            },
            {  
              "countryId":"2",
              "countryName":"XYZ"
            },
            {  
              "countryId":"3",
              "countryName":"PQR"
            }
          ]
        }
      ]
    }
    
    
    var selCountries =    [  
      {  
        "countryId":"1"
      },
      {  
        "countryId":"3"
      }
    ];
    
    product.layers = product.layers.map(function (layer) {
      return layer.countries.filter(function (country) {
        return selCountries.some(function(selCountry) {
          return selCountry.countryId === country.countryId;
        });
      });
    });
    
    console.log(product);

    【讨论】:

      猜你喜欢
      • 2020-12-20
      • 1970-01-01
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-23
      • 2019-01-29
      • 1970-01-01
      相关资源
      最近更新 更多