Search code examples
javascriptnode.jsdata-modeling

Transforming an array to a sorted object


I have in input an array of arrays such as :

[
  [ '1', '12:23', '16:27' ],
  [ '1', '08:00', '17:59' ],
  [ '2', '14:50', '15:14' ],
  [ '2', '09:42', '11:00' ],
  [ '3', '17:16', '17:41' ],
  [ '3', '08:00', '17:59' ],
  [ '4', '08:10', '13:01' ],
]

I'd like to be able to use the first element of the arrays as a key object, to store the second and third element in it, sorted by the second one, as this :

  {
    1: [
      ['08:00', '17:59'],
      ['12:23', '16:27'],
    ],
    2: [
      ['09:42', '11:00'],
      ['14:50', '15:14'],
    ]
    3: [
      ['08:00', '17:59'],
      ['17:16', '17:41'],
    ]
    4: [
      ['08:10', '13:01'],
    ]      
  }

Hints?


Solution

  • Converting an array into an object is an ideal candidate for using Array.prototype.reduce() :

    const arr = [
      [ '1', '12:23', '16:27' ],
      [ '1', '08:00', '17:59' ],
      [ '2', '14:50', '15:14' ],
      [ '2', '09:42', '11:00' ],
      [ '3', '17:16', '17:41' ],
      [ '3', '08:00', '17:59' ],
      [ '4', '08:10', '13:01' ],
    ];
    
    const obj = arr.reduce((acc, item) => {
      const [key, timeA, timeB] = item;
      
      // create array of time pairs if necessary
      acc[key] = acc[key] || [];
      
      // add time pairs to array
      acc[key].push([timeA, timeB]);
      
      return acc;
    }, {});
    
    // sort the time pair arrays by the first time
    const compare = (a, b) => {
      const aTime = a[0],
        bTime = b[0];
      return aTime.localeCompare(bTime);
    };
    Object.values(obj).forEach(arr => {
      arr.sort(compare);
    });
    
    document.querySelector('pre').innerText = 'obj ' +
      JSON.stringify(obj, null, 2);
    <pre></pre>