Search code examples
javascriptarraysjavascript-objectsramda.js

How to convert an array of objects into an array of arrays using Ramda


I would like to transform this:

[
  { a: 2000, b: 4000 },
  { a: 8000, b: 5000 },
  { a: 6000, b: 1000 }
];

Into this:

[
  [ 2000, 8000, 6000 ],
  [ 4000, 5000, 1000 ]
];

Using Ramda.

I can do this using just R.reduce, but I'm wondering if there's a way that uses as little custom code as possible and instead makes full use of the functions Ramda provides.

One more caveat; the solution can't assume that the keys in the objects are known. They will always be consistent between objects, but may change every time this function is run. For example, the next run of the code could be:

Input:

[
  { c: 1000, d: 4000, e: 7000 },
  { c: 2000, d: 5000, e: 8000 },
  { c: 3000, d: 6000, e: 9000 }
];

Result:

[
  [ 1000, 2000, 3000 ],
  [ 4000, 5000, 6000 ],
  [ 7000, 8000, 9000 ],
];


Solution

  • Just use vanilla JS and transpose the mapped object values.

    transpose(input.map(Object.values));
    

    const transpose = (a) => a[0].map((_, i) => a.map(r => r[i]));
    
    {
      const
        input = [
          { a: 2000, b: 4000 },
          { a: 8000, b: 5000 },
          { a: 6000, b: 1000 }
        ],
        expected = [
          [ 2000, 8000, 6000 ],
          [ 4000, 5000, 1000 ]
        ],
        actual = transpose(input.map(Object.values));
    
      console.log(JSON.stringify(actual) === JSON.stringify(expected));
    }
    
    {
      const
        input = [
          { c: 1000, d: 4000 },
          { c: 2000, d: 5000 },
          { c: 3000, d: 6000 }
        ],
        expected = [
          [ 1000, 2000, 3000 ],
          [ 4000, 5000, 6000 ]
        ],
        actual = transpose(input.map(Object.values));
    
      console.log(JSON.stringify(actual) === JSON.stringify(expected));
    }

    Here is the equivalent in Rambda:

    R.transpose(R.map(R.values, input));             // or
    R.transpose(R.compose(R.map(R.values))(input));
    

    {
      const
        input = [
          { a: 2000, b: 4000 },
          { a: 8000, b: 5000 },
          { a: 6000, b: 1000 }
        ],
        expected = [
          [ 2000, 8000, 6000 ],
          [ 4000, 5000, 1000 ]
        ],
        actual = R.transpose(R.map(R.values, input));
    
      console.log(JSON.stringify(actual) === JSON.stringify(expected));
    }
    
    {
      const
        input = [
          { c: 1000, d: 4000 },
          { c: 2000, d: 5000 },
          { c: 3000, d: 6000 }
        ],
        expected = [
          [ 1000, 2000, 3000 ],
          [ 4000, 5000, 6000 ]
        ],
        actual = R.transpose(R.map(R.values, input));
    
      console.log(JSON.stringify(actual) === JSON.stringify(expected));
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.29.0/ramda.min.js"></script>