0

So I would need to filter array and an array within this array.

So, we have an array -

arr: [
   {
      name: 'object',
      array2: [
         {
            name: '1'
         },
         {
            name: '2'
         }
      ]
   },
   {
      name: 'object 2',
      array2: [
         {
            name: 'object'
         }
      ]
   }
]

I enter a value 2 in the filter, and the output, that I would like to have here is -

arr: [
   {
      name: 'object',
      array2: [
         {
            name: '2'
         }
      ]
   },
   {
      name: 'object 2',
      array2: []
   }
]

I have the matching logic here, and it works on the outer level (the first level, where I have an object with name and array2 parameters). The inner level also works, but the issue here is that, if I filter the inner level, I'm not able to get back the initial state of the inner objet, that is. I have an input bar, if I enter 2, it's filtered just fine, but, if I remove 2, then it shows other elements from arr: [], but doesn't show filtered elements from array2: [].

Any ideas on how to fix this?

Link to jsFiddle with comments - http://jsbin.com/pupugoxebi/edit?html,js,output .

I coudl manually push in the new array, but this doesn't work because I have dynamic array, for example, it can have different properties, and writing manually won't solve it. Updated version - http://jsbin.com/bifolisefu/edit?html,js,output .

2
  • please add your code and the wanted result as well. you may have a look here, too: minimal reproducible example Commented Apr 10, 2017 at 14:32
  • Done. Added link to jsFiddle + comments of what I expected, but what I got. If we filter first time on 3, for example, it works just fine, but if we delete the 3 and filter it on something else - it doesn't work anymore. Commented Apr 10, 2017 at 14:47

2 Answers 2

1

You could use either the ceck for the name of the outer array or check if the inner array returns some items, then build a new object and concat it to the result set.

function getNodes(array, name) {
    return array.reduce(function (r, a) {
        var temp = a.array2.filter(b => b.name.includes(name));
        return r.concat(
            a.name.includes(name) || temp.length ?
            Object.assign({}, a,  { array2: temp }) :
            []
        );
    }, []);
}

var array = [{ name: 'test', foo: 0, array2: [{ name: 'test 2', foo: 1 }, { name: 'test 3', foo: 2 }] }, { name: 'test 2', foo: 3, array2: [{ name: 'test', foo: 4 }] }, { name: 'test 3', foo: 5, array2: [{ name: 'test 4', foo: 6 }, { name: 'test 5', foo: 7 }] }];

console.log(getNodes(array, '2'));
console.log(getNodes(array, '3'));
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

8 Comments

This does not work, becauase I cannot create dynamically array, the cause for this is that it doesn't have known amount of properties and property names. I know onyl the onse specified, but there can also be others - it's created dynamically. So, e.g., there could also be properties like - otherValue, longitude, latitude, and so on and forth. That is - array and array2 is created dynamically with lot of properties (dynamic properties), and I know only the properties which will need to be filtered.
i chaged it to a dynamic approach with Object.assign.
Just wondering if it' s possible to do it without concat? And using only two filters? Liek here - jsbin.com/yadifeboto/edit?html,js,output . The cause is that I'm using typescript and craeting custom types, and there are multiple types for which concat does not exist. If no, that's fine. Just wondering
actually no, because filter gets parts pf the original array, but does not change the content. you need a changed content, if you want to get the outer part without array2.
that's right, it works onyl a method which allows to change the return value, like reduce or map (this works for all items).
|
0

Try the following code.

var arr2 = [
  {
    name: 'test',
    array2: [
      {
        name: 'test 2'
      },
      {
        name: 'test 3'
      }
    ]
  },
  {
    name: 'test 2',
    array2: [
      {
        name: 'test'
      }
    ]
  },
  {
    name: 'test 3',
    array2: [
      {
        name: 'test 4'
      },
      {
        name: 'test 5'
      }
    ]
  }
];

arr2.map(e => {
  var tmp = e.array2.filter(e2 => e2.name.includes('2'));
  e.array2 = tmp;
});

console.log(arr2);

4 Comments

This does not work. It does not filter the big array based on the text.
What do you mean by that? Doesn't the structure of the answer conforms to your specification?
No, it unfortunately, does not. the expected array would be without { "name": "test 3", "array2": [] } object.
In additional it overwrites the original array, and that is not required. I need to execute multiple times the filtering on the array. It would work as a search in array. Imagine you would have an input field instead of the constant '2', and every input would execute the code. And deleting a value from the input field would execute the filter also, so in case input is empty, then nothing should be filtered and original array should be returned, e.t.c. this is why original array cannot be modified.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.