0

I have an array of objects with one property being an array of values without keys and I am attempting to filter through and check for matching values within the nested array. Here is an example of one object:

[ 0:
    { fiber_phases: ["45", "46"],
      id: 1,
      label: "3200 to 3299 1 1/2 ST N",
      max_number: "3299",
      min_number: "3200",
      parsed_hash: "4028c7befc61ba4d07189f6ba99de35f",
      street: "1 1/2 ST N" 
    }
]

Here is my javascript code thus far:

return this.blocks
    .filter((block) => block.fiber_phases === fiberPhase)
    .map(({id, label, max_number, min_number, street, parsed_hash, fiber_phases}) => ({id: id, label: label, max_number: max_number, min_number: min_number, street: street, parsed_hash: parsed_hash, fiber_phases: fiber_phases}))

It's pretty clear that I'm not actually going into the nested array, but I haven't been able to access it.

7
  • 1
    I am attempting to filter through and check for matching values within the nested array. is definitely not clear. Commented Feb 27, 2018 at 19:01
  • 1
    I agree with @void, can you post an example of the input and desired output? Commented Feb 27, 2018 at 19:02
  • Instead of block.fiber_phases === fiberPhase did you intend to do block.fiber_phases.includes(fiberPhase)? Commented Feb 27, 2018 at 19:03
  • 1
    I'll rephrase. My goal is to filter through an array of objects (all 11,231 of them), which each have a nested array of fiber_phases, and check for matches based on one fiberPhase value (i.e. let fiberPhase = '46'). I then would like to return a new array of objects that match that value. Commented Feb 27, 2018 at 19:03
  • Instead of id: id, just do id, Commented Feb 27, 2018 at 19:06

2 Answers 2

2

If you want to filter your main array such that it only contains objects that have fiberPhase anywhere in their fiber_phases array, you'd use filter with includes in the predicate:

return this.blocks.filter(block => block.fiber_phases.includes(fiberPhase));

Array.prototype.includes is relatively recent, but trivial to polyfill (see the link above). Or if you don't want to, indexOf will work:

return this.blocks.filter(block => block.fiber_phases.indexOf(fiberPhase) !== -1);

Note that that will return a new array which shares the objects with the original. If you wanted to copy them, you'd add

.map(entry => Object.assign({}, entry))

to it, or with some Stage 4 syntax that will be in the ES2018 spec:

.map(entry => ({...entry}))

Either way, it's a shallow copy (the fiber_phases array will be shared).

Adjust as needed.

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

4 Comments

@MattLarson: FWIW, if you need to repeatedly filter the same array, and if you run into performance problems, it may be worth building a fiberPhase-to-array map once (with the attendant memory hit) which you can then reuse...
Interesting. I'm also attempting to returning objects that contain a value match in the nested array and no other values :/ So right now, .filter((block) => block.fiber_phases.includes(fiberPhase)) will return results sets that match fiberPhase and ones that match other fiberPhases as well. If only there was an .onlyIncludes() hah
@MattLarson: Wouldn't that be block => block.fiber_phases.length == 1 && block.fiber_phases[0] == fiberPhase ? :-)
I think that'd work! I'm having another issue, so I'll check in a moment.
1

You can achieve that with includes and Object.assign:

return this.blocks
    .filter(block => block.fiber_phases.include(fiberPhase))
    .map(block => Object.assign({}, block));

Or with the more recent ECMAScript 2018 spread syntax for object literals:

return this.blocks
    .filter(block => block.fiber_phases.include(fiberPhase))
    .map(block => ({...block}));

Comments

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.