Siddarth
Siddarth

Reputation: 69

Group by array with first letter in javascript

I Have array like

['Ajith', 'Arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya', 'Kavitha', 'Kamal', 'Bavi']

I want ouptut like

   ['A',
    'Ajith',
    'Arya',
    'Akila',
    'B',
    'Bharath',
    'Bhakya',
    'Bavi',
    'k',
    'Kamal']

how can i acheive this in javascript Help me and thanks advance

Upvotes: 0

Views: 196

Answers (10)

Andrew Parks
Andrew Parks

Reputation: 8087

let d=["Ajith","Arya","Akalya","Akila",
  "Bharath","Bhakya","Kavitha","Kamal","Bavi"].sort()
  
let r=[...new Set(d.map(([c])=>c))].flatMap(c=>[c, ...d.filter(([i])=>i==c)])

console.log(r)

or:

let d = ["Ajith","Arya","Akalya","Akila",
  "Bharath","Bhakya","Kavitha","Kamal","Bavi"].sort()

let r = Object.values(d.map(s=>
  [s.charAt(0),s]).reduce((c,[a,b])=>((c[a]??=[a]).push(b),c),{})).flat()

console.log(r)

Upvotes: 1

Jan Pfeifer
Jan Pfeifer

Reputation: 2861

Several good answers are already here. This one may be a little bit simpler:

const arr = ['Ajith', 'Arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya', 'Kavitha', 'Kamal', 'Bavi'].sort();
for(let i = arr.length -1; i>=0; i--) {
    if(i === 0 || arr[i][0] !== arr[i-1][0]) arr.splice(i,0, arr[i][0]);
}

console.log(arr);

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386560

You could group by first uppercase character with the character and all following items in a flat array.

const
    data = ['Ajith', 'Arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya', 'Kavitha', 'Kamal', 'Bavi'],
    result = Object
        .values(data.reduce((r, s) => {
            const key = s[0].toUpperCase();
            (r[key] ??= [key]).push(s);
            return r;
        }, {}))
        .sort(([a], [b]) => a.localeCompare(b))
        .flat();

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Lionel Ding
Lionel Ding

Reputation: 192

let names = ['Ajith', 'Arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya', 'Kavitha', 'Kamal', 'Bavi'];

let result = [];

let firstLetters = new Set();
for (let i = 0; i < names.length; i++) {
  firstLetters.add(names[i][0]);
}

firstLetters = Array.from(firstLetters).sort();
for (let i = 0; i < firstLetters.length; i++) {
  result.push(firstLetters[i]);
  for (let j = 0; j < names.length; j++) {
    if (names[j][0] === firstLetters[i]) {
      result.push(names[j]);
    }
  }
}

console.log(result);

Upvotes: 0

mplungjan
mplungjan

Reputation: 177786

Something like this? Seems simpler than what was posted so far

const arr = ['Ajith', 'Arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya', 'Kavitha', 'Kamal', 'Bavi']
const newArr = arr
  .slice() // copy 
  .sort();
let letter = "";  
for (let i=0; i<newArr.length; i++) {
  const thisLetter = newArr[i].charAt(0);
  if (thisLetter !== letter) {
    letter = thisLetter;
    newArr.splice(i,0,thisLetter)
  }
}  
console.log(newArr)

Upvotes: 1

I_Al-thamary
I_Al-thamary

Reputation: 3993

You can use map

let names = ['Ajith', 'Arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya', 'Kavitha', 'Kamal', 'Bavi'];

let map = new Map();
names.forEach(item => {
  let firstLetter = item[0].toUpperCase();
  if (!map.has(firstLetter)) {
    map.set(firstLetter, [firstLetter]);
  }
  map.get(firstLetter).push(item);
});

let result = [];
map.forEach(value => {
  result.push(...value);
});

console.log(result);

You can also make every letter a separate group

let name = ['Ajith', 'arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya', 'Kavitha', 'Kamal', 'Bavi'];

let map = new Map();
name.forEach(item => {
  let firstLetter = item[0].toUpperCase();
  if (!map.has(firstLetter)) {
    map.set(firstLetter, [firstLetter]);
  }
  map.get(firstLetter).push(item);
});

let result = [];
map.forEach(value => {
  result.push(value);
});

console.log(result);

Upvotes: 0

Baptiste Delpierre
Baptiste Delpierre

Reputation: 46

Here's a solution, probably not the most optimized one, but it should work :

The idea is to sort the array, loop over all the elements to compare the first letter in order to create a subgroup title.

It would look something like this :

var displaySortedArray = function(array) {
  var sortedArray = array.sort();
  console.log(sortedArray[0].charAt(0));
  console.log(sortedArray[0]);
  for(let index = 1 ; index < sortedArray.length ; index++){
    if(sortedArray[index].charAt(0) != sortedArray[index-1].charAt(0)){
      console.log(sortedArray[index].charAt(0));
    }
    console.log(sortedArray[index]);
  }
}

displaySortedArray(['Test','SUUUU','Easy','Try2','Elements','Super','Amazing']);
This function is an example and prints what you asked for, however i can't tell you how to implement this where you need it.

Have a good day.

Upvotes: 2

This is possible to do using a single reduce call which I find quite elegant:

const data = ['Ajith', 'Arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya', 'Kavitha', 'Kamal', 'Bavi'];
console.log(
  data
    .sort()
    .reduce(
      (items, item, index, array) => {
        console.log({ prev: array[index - 1], current: item });
        if (array[index - 1]?.[0] !== item[0]) {
          items.push(item[0]);
        }

        items.push(item);
        return items;
      },
      []
    )
);

Codepen

Upvotes: 1

Robby Cornelissen
Robby Cornelissen

Reputation: 97130

Can reduce() everything to an object, indexed by the first letter:

const data = ['Ajith', 'Arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya',
              'Kavitha', 'Kamal', 'Bavi'];

const result = [...data].sort().reduce((a, v) => {
  const [first] = v;
  a[first] ??= [];
  a[first].push(v);
  return a;
}, {});

console.log(result);

This object will have the keys in the correct order because sort() was called first on (a copy of) the array, and string keys are maintained in insertion order.

If you want to convert that object to a flat array, you can just do:

const array = Object.keys(result).flatMap((k) => [k, ...result[k]]);

Upvotes: 2

pilchard
pilchard

Reputation: 12909

You can simply do as your title says — 'group-by' first letter, then map the result.

const input = ['Ajith', 'Arya', 'Akalya', 'Akila', 'Bharath', 'Bhakya', 'Kavitha', 'Kamal', 'Bavi',];


const grouped = {};

for (const word of input) {
  (grouped[word[0].toUpperCase()] ??= []).push(word);
}

const result = Object.entries(grouped).flatMap(([k, vs]) => [k, ...vs]);

console.log(result);

Upvotes: 2

Related Questions