如何在多个条件下过滤嵌套的对象数组?

时间:2018-07-25 22:20:48

标签: javascript node.js ecmascript-6

下面是对象的示例数组。 我正在基于criteriaTypeidsource进行过滤。如果input.source都不匹配,则应滤除父对象。同样,所有过滤条件都是可选的。

[{
    "id": "9be6c6299cca48f597fe71bc99c37b2f",
    "caption": "caption1",
    "criteriaType": "type2",
    "input": [
        {
            "id_1": "66be4486ffd3431eb60e6ea6326158fe",
            "criteriaId": "9be6c6299cca48f597fe71bc99c37b2f",
            "source": "type1",
        },
        {
            "id_1": "1ecdf410b3314865be2b52ca9b4c8539",
            "criteriaId": "9be6c6299cca48f597fe71bc99c37b2f",
            "source": "type2",
        }
    ]
},
{
    "id": "b83b3f081a7b45e087183740b12faf3a",
    "caption": "caption1",
    "criteriaType": "type1",
    "input": [
        {
            "id_1": "f46da7ffa859425e922bdbb701cfcf88",
            "criteriaId": "b83b3f081a7b45e087183740b12faf3a",
            "source": "type3",
        },
        {
            "id_1": "abb87219db254d108a1e0f774f88dfb6",
            "criteriaId": "b83b3f081a7b45e087183740b12faf3a",
            "source": "type1",
        }
    ]
},
{
    "id": "fe5b071a2d8a4a9da61bbd81b9271e31",
    "caption": "caption1",
    "criteriaType": "type1",
    "input": [
        {
            "id_1": "7ea1b85e4dbc44e8b37d1110b565a081",
            "criteriaId": "fe5b071a2d8a4a9da61bbd81b9271e31",
            "source": "type3",
        },
        {
            "id_1": "c5f943b61f674265b8237bb560cbed03",
            "criteriaId": "fe5b071a2d8a4a9da61bbd81b9271e31",
            "source": "type3",
        }
    ]
}]

我能够仅通过criteriaTypeid进行过滤。但是我也无法通过source进行过滤,以确保在input.source都不匹配的情况下不返回父级。

var json = <<array of objects>> ;
const {objectId: id, ctype: criteriaType, inputSource: source } = param; // getting the the params
json = ctype ? json.filter(({criteriaType}) => criteriaType === ctype ): json;
json = (objectId ? json.filter(({id}) => id === objectId ): json)
       .map (({id, caption, criteriaType, input }) => {
         //some manipulation 
         return { //results after manipulation}
       })

帮帮我!提前致谢。我不确定是否可以链接过滤器来实现它。

寻找esLint兼容代码

5 个答案:

答案 0 :(得分:1)

有两种解决方法。您可以在纯JS中实现此功能,建议使用Lodash

1)Lodash filter s

``` javascript
var users = [
  { 'user': 'barney', 'age': 36, 'active': true },
  { 'user': 'fred',   'age': 40, 'active': false }
];

_.filter(users, function(o) { return !o.active; });
// => objects for ['fred']

// The `_.matches` iteratee shorthand.
_.filter(users, { 'age': 36, 'active': true });
// => objects for ['barney']

// The `_.matchesProperty` iteratee shorthand.
_.filter(users, ['active', false]);
// => objects for ['fred']

// The `_.property` iteratee shorthand.
_.filter(users, 'active');
// => objects for ['barney']
```

2)JavaScript ES5 filter()

``` javascript
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

var result = words
  .filter(word => word.length > 6)
  .filter(word => word.length < 8);

console.log(result);
// expected output: Array ["present"]
```

2)MapReduce

MapReduce是我最喜欢的用于处理集合/集合的工具之一。

您在上面的代码中使用了map()。诀窍可能是将map更改为reduce

使用map,进出的收藏品比例为1-1。

使用reduce,您可以为输入中的每个项目生成尽可能多的项目。例如

``` javascript
var stuff = ['couch', 'chair', 'desk'];

var hasFiveLetters = stuff.reduce((total, item) => {
  if (item.length === 5) total.push(item);  // add to total any items you like
  return total;  // don't forget to return total!
}, []);  // initialize total to []

console.log(hasFiveLetters); // ['couch', 'chair'];

```

答案 1 :(得分:1)

要求是过滤器,它是可选的,并且不返回任何与父项匹配的源https://jsfiddle.net/cpk18dt4/9/

注释在代码中。希望它能解释该功能的作用。

const fnFilter = (criteriaType, id, source) => {
  let result = oData;

  if (criteriaType) { // it can be null (optional)
    result = result.filter(d => d.criteriaType === criteriaType);
  }
  if (id) { // it can be null (optional)
    result = result.filter(d => d.id === id);
  }
  if (source) { // it can be null (optional)
    result = result.filter(d => {
      const inputs = d.input.filter(inp => inp.source === source);

      // If none of the input.source match, the parent object should be filtered out
      if (inputs.length === 0) {
        return false;
      }
      d.input = inputs;
      return true;
    });
  }

  return result;
};

答案 2 :(得分:0)

Lodash查找和过滤器可用于此目的。与过滤器相比,查找在嵌套数组中的匹配速度更快,它需要匹配首次出现的匹配器。

json = ctype ? _.filter(json, function(o) {
    return o.criteriaType === ctype;
}) || json;
json = objectId ? _.filter(json, function(o) {
    return o.id === objectId;
}) || json;
json = source ? _.filter(json, function(o) {
    return _.find(o.input, function(input_object) {
        return input_object.source === source;
    });
}) || json;

答案 3 :(得分:0)

尝试一下:

    var obj = [{
        "id": "9be6c6299cca48f597fe71bc99c37b2f",
        "caption": "caption1",
        "criteriaType": "type2",
        "input": [
            {
                "id_1": "66be4486ffd3431eb60e6ea6326158fe",
                "criteriaId": "9be6c6299cca48f597fe71bc99c37b2f",
                "source": "type1",
            },
            {
                "id_1": "1ecdf410b3314865be2b52ca9b4c8539",
                "criteriaId": "9be6c6299cca48f597fe71bc99c37b2f",
                "source": "type2",
            }
        ]
    },
    {
        "id": "b83b3f081a7b45e087183740b12faf3a",
        "caption": "caption1",
        "criteriaType": "type1",
        "input": [
            {
                "id_1": "f46da7ffa859425e922bdbb701cfcf88",
                "criteriaId": "b83b3f081a7b45e087183740b12faf3a",
                "source": "type3",
            },
            {
                "id_1": "abb87219db254d108a1e0f774f88dfb6",
                "criteriaId": "b83b3f081a7b45e087183740b12faf3a",
                "source": "type1",
            }
        ]
    },
    {
        "id": "fe5b071a2d8a4a9da61bbd81b9271e31",
        "caption": "caption1",
        "criteriaType": "type1",
        "input": [
            {
                "id_1": "7ea1b85e4dbc44e8b37d1110b565a081",
                "criteriaId": "fe5b071a2d8a4a9da61bbd81b9271e31",
                "source": "type3",
            },
            {
                "id_1": "c5f943b61f674265b8237bb560cbed03",
                "criteriaId": "fe5b071a2d8a4a9da61bbd81b9271e31",
                "source": "type3",
            }
        ]
    }];
    
      
    function filterObj(obj, column, value){
    	var newArray = obj.filter(function (el) {
      	    if(el[column]){
        	    return el[column] == value;
            }else{
        	    for(var key in el.input){
                    if(typeof(el.input[key] == "object")){
                        var item = el.input[key];
                        if(item[column] == value){return item;}
                    }
                }
            }
    	});
        return newArray;
    }
    
    console.log(filterObj(obj, 'caption','caption1'));
    console.log(filterObj(obj, 'criteriaId','fe5b071a2d8a4a9da61bbd81b9271e31'));
    console.log(filterObj(obj, 'id_1','1ecdf410b3314865be2b52ca9b4c8539'));

答案 4 :(得分:0)

// if field has a value, filter on it, else return original json
const having = (json, field, val) =>
  val ? json.filter(j => j[field] === val) : json

const filterBySource = (json, source) => {
  if (!source) return json
  return json.filter(
    j => j.input.length > 0 && j.input.some(input => input.source === source)
  )
}

function search(json, params = {}) {
  const { objectId: id, ctype: criteriaType, inputSource: source } = params

  // if no filters, return the whole json
  if (!(id || criteriaType || source)) return json

  let result
  result = having(json, 'id', id)
  result = having(result, 'criteriaType', criteriaType)

  return filterBySource(result, source)
}

const params = {
  objectId: 'fe5b071a2d8a4a9da61bbd81b9271e31',
  ctype: 'type1',
  inputSource: 'type3'
}

search(json, params).map(({ id, caption, criteriaType, input }) => {
  // do something with filtered json
})