0

I have an array of objects

const a = [
  { name: 'z', items: [..] },
  { name: 'x', items: [..] },
  { name: 'y', items: [..] },
  { name: 'a', items: [..] },
]

I would like to select and reorder such that I transform the array into

const a_new = [
  { name: 'x', items: [..] },
  { name: 'y', items: [..] },
  { name: 'z', items: [..] },
]

i.e. I only want those with name x, y, and z and I want it ordered by some specific order (not just alphanumerically).

So I would like to, for instance, specify an array ['x', 'y', 'z'], indicating which names I would allow and how they should be sorted.

Could it be something like

['x', 'y', 'z'].map(allowedValue => a.find(b => b.name === allowedValue))

It just seems a bit memory heavy?

4
  • 2
    Why not call filter and sort as indicated by your title? Commented Nov 4, 2017 at 21:14
  • What is issue with ['x', 'y', 'z'].map(allowedValue => a.find(b => b.name === allowedValue))? What do you mean by "memory heavy"? Commented Nov 4, 2017 at 21:18
  • 2
    You could reduce a to a “hash map” object where the keys are the values of the name property of each object, then map ["x", "y", "z"] to the objects that you can look up from the hash map. This should yield a time complexity of O(n), but the space complexity would be worse. Commented Nov 4, 2017 at 21:31
  • Ultimate answer really depends on size of data sets Commented Nov 4, 2017 at 21:43

2 Answers 2

2

You could build a Map out of a:

const byName = new Map(a.map( obj => [obj.name, obj]));

So now we can easily get the result in O(n):

 const result = ['x', 'y', 'z'].map(name => byName.get(name));

This should be faster than your solution, however its memory consumption is much higher.

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

7 Comments

Unfortunately it's even slower than the filter&sort solution.
@Kinduser I doubt that… for larger inputs, this solution should be faster.
@kind user i think O(2n) is faster than O(n * log n) or am i wrong?
Just tested it on two different benchmarks and yeah, it is slower. I'm not saying that it's wrong, just lil bit slower then the other solutions. However, tested it on the same array as OP provided.
But... why? How can you be so sure that OP going to handle arrays of 1000+ size?
|
1

You could firstly filter specified elements with Array#filter and then sort it according to index of given element inside the b (schema) array.

const a = [
  { name: 'z', items: [] },
  { name: 'x', items: [] },
  { name: 'y', items: [] },
  { name: 'a', items: [] },
];

const b = ['x', 'y', 'z'];

const c = a.filter(({ name }) => b.includes(name))
           .sort(({ name: r }, { name: t }) => b.indexOf(r) - b.indexOf(t));
           
console.log(c);

10 Comments

@Xufox He asked for a sorting solution (he tagged sorting keyword aswell) so here it is.
No, he asked whether the code he already showed was good enough and used little enough memory. He was not asking for a sorting solution.
@Xufox I got a different opinion, however I'm pretty curious if it will be faster than his actual solution. Going to test it now.
I would bet it is faster since find() has to do a lot of iterations
@charlietfl Doesn’t includes have the same problem as find?
|

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.