1

I'm trying to build an array of objects out of another array of objects:

  const items = [
    {
      id: 'thing-1',
      size: {
        height: 50
      },
    },
    {
      id: 'thing-2',
      size: {
        height: 100
      }
    },
    {
      id: 'thing-3',
      size: {
        height: 500
      }
    },
    {
      id: 'thing-4',
      size: {
        height: 200
      }
    }
  ];

Here's my expected results:

  const newList = [
    {id: 'thing-1', top: 0},
    {id: 'thing-2', top: 50},
    {id: 'thing-3', top: 150},
    {id: 'thing-4', top: 650},
  ];

Basically I'm trying to find the top position if all items are stacked on top of each other. As it builds the new list, it calculates the top position of each item (relative to the stack of items). So if the first item is at the top of the stack (0 from the top) and is 50 high, the second item is 50 from the top. The height of the last item is irrelevant.

I have a feeling a reduce can be used in this situation but I'm not exactly sure on how to form the syntax in this situation.

I tried something like this but it's not quite right. Also if I could do this without creating an empty array outside the scope of the reduce that'd be preferable.

  const itemsReduced = [];

  items.reduce((acc, elm) => {
    itemsReduced.push({id: elm.id, top: acc + elm.size.height});
    return elm.size.height;
  });

  console.log(itemsReduced);

Tried that, but it just resulted in this.

[
  {id: "thing-2", top: "[object Object]100"},
  {id: "thing-3", top: 600},
  {id: "thing-4", top: 700},
]

I was thinking about a basic loop but it still needs the context of the item before it as it iterates through.

Matt Coady
  • 3,418
  • 5
  • 38
  • 63

1 Answers1

1

Here is a simple solution using reduce

const items = [{id: 'thing-1', size: {height:  50}},
               {id: 'thing-2', size: {height: 100}},
               {id: 'thing-3', size: {height: 500}},
               {id: 'thing-4', size: {height: 200}}
              ];

var result = items.reduce((a, v) => {
  a.res.push({ id: v.id, top: a.i });
  a.i += v.size.height;
  return a;
}, { res: [], i: 0 } ).res;

console.log(JSON.stringify(result));

I simply use an object as the initialiser of reduce, having two properties: res which is the resulting array we want to get, and i which is the accumulation of the tops.
When the object is returned at the end, I simply get its res property.

theAlexandrian
  • 870
  • 6
  • 18