1

I'm wondering, I have the following data structure:

data = [
  {
    name: 'Alpha',
  },
  {
    name: 'Alfa',
  },
  {
    name: 'Bravo',
  },
  {
    name: 'Brafo',
  },
  {
    name: 'Charlie',
  },
  {
    name: 'Charly',
  },
  ...
  {
    name: 'Zulu',
  },
  {
    name: 'Zulo',
  },
]

I'm expecting there to be at least one, usually more, key for each letter of the alphabet. However, if there isn't a single data.name I would still like in the below data structure to have an empty domains array [].

I was wondering, how could this be manipulated into the following data structure:

data = {
  a: {
    domains: [
      {
        name: 'Alpha',
      },
      {
        name: 'Alfa',
       },
    ],
  },
  b: {
    domains: [
      ...
    ]
  },
  ...
  z: {
    domains: [
      ...
    ]
  },
};

I have used a few methods, which involved a pre-constructed "alphbetised" key = object array, then filtered each on the first letter of the data.name value...but I was wondering if there was a standard and performant method to acheive this?

Micheal J. Roberts
  • 3,735
  • 4
  • 37
  • 76
  • 1
    Does this answer your question? [Sort and group objects alphabetically by first letter Javascript](https://stackoverflow.com/questions/51009090/sort-and-group-objects-alphabetically-by-first-letter-javascript) – Ivar Jul 22 '20 at 11:31
  • @Ivar Hi Ivar, not quite ... it's as slightly different way of key - value ordering. – Micheal J. Roberts Jul 22 '20 at 11:32
  • maybe you are looking for a [trie](https://en.wikipedia.org/wiki/Trie) ... – Nina Scholz Jul 22 '20 at 11:32
  • I think it is some sort of trie - but I haven't seen the specific use case for my need... – Micheal J. Roberts Jul 22 '20 at 11:34
  • @MichealJ.Roberts Slightly different how? If you remove the `group` and rename `children` to `domains`, [it looks almost identical to you example](https://jsfiddle.net/esqzg9o8/1/). – Ivar Jul 22 '20 at 11:37

2 Answers2

3

Using reduce()

const data = [{name:"Alpha"},{name:"Alfa"},{name:"Bravo"},{name:"Brafo"},{name:"Charlie"},{name:"Charly"},{name:"Zulu"},{name:"Zulo"}]

const res = data.reduce((a, v) => {
  // prepare key
  let key = v.name.substring(0,1).toLowerCase()
  
  // check key in accumulator
  if (!a[key]) {
    // assign domain object
    a[key] = {domains: []}
  }
  
  // push domain array
  a[key].domains.push(v)
  
  return a
}, {}) 

console.log(res)
User863
  • 19,346
  • 2
  • 17
  • 41
3

Here is what you want:

data = [
    {
        name: 'Alpha',
    },
    {
        name: 'Alfa',
    },
    {
        name: 'Bravo',
    },
    {
        name: 'Brafo',
    },
    {
        name: 'Charlie',
    },
    {
        name: 'Charly',
    },
    {
        name: 'Zulu',
    },
    {
        name: 'Zulo',
    },
];

console.log(data.reduce((a, c) => {
    const firstLetter = c.name[0].toLowerCase();
    if (a[firstLetter]) {
        a[firstLetter].domains.push(c);
    } else {
        a[firstLetter] = { domains: [c] };
    }
    return a;
}, {}));
8HoLoN
  • 1,122
  • 5
  • 14