Techdive
Techdive

Reputation: 1043

How to sort and group and divide the array alphabetically in angular2+

I want to display the content of the buttons according to the alphabetical order and divide them in groups like A-H, I-Q and R-Z. My code is written in angular2+.

Alphabetic division

My array is -

this.dropdownList = [
      { item_text: 'Organisation' },
      {  item_text: 'EwayBill' },
      {  item_text: 'SAP' },
      {  item_text: 'Collection' },
      {  item_text: 'Cancel' },
      {  item_text: 'Generate' },
      {  item_text: 'Payments' },
      {  item_text: 'SMS' },
      {  item_text: 'Update' }
]

Upvotes: 0

Views: 914

Answers (3)

Techdive
Techdive

Reputation: 1043

By manipulating the mentioned codes, i framed a code as such -

 Proceed() {


// some basic interfaces to describe types
interface Item {
  item_text: string;
}
interface LetterRange {
  first: string;
  last: string;
}

// the letter ranges
// this solution allows them to intersect
// can adjust for any letter ranges
const rangesAtoH: LetterRange[] = [
  {first: 'a', last: 'h'},

];

const rangesItoQ: LetterRange[] = [

  {first: 'i', last: 'q'},

];

const rangesRtoZ: LetterRange[] = [

  {first: 'r', last: 'z'}
];

const dropdownParameter: Item[] = [
  { item_text: 'Organisation' },
  {  item_text: 'EwayBill' },
  {  item_text: 'SAP' },
  {  item_text: 'Collection' },
  {  item_text: 'Cancel' },
  {  item_text: 'Generate' },
  {  item_text: 'Payments' },
  {  item_text: 'SMS' },
  {  item_text: 'Update' }
];

// sort the words alphabetically so that they will appear in the right order
const sorted: Item[] = this.dropdownParameter.sort((a,b) => a.item_text.localeCompare(b.item_text));

console.log("inside Proceed, Sorted = ", sorted)


// --------------------------  Array 2 - suggestion-----------------------------

// array of grouped items (each group is array as well)
const grouped: Item[][] = sorted.reduce((groups, item) => {
  const firstLetter: string = item.item_text.slice(0,1).toLowerCase();
  console.log(firstLetter);

  // run through each range and check whether the 'firstLetter' fits there
  rangesAtoH.forEach((range, index) => {
    if (firstLetter >= range.first.toLowerCase()
       && firstLetter <= range.last.toLowerCase()) {
      groups[index].push(item);
    }
  });
  return groups;
}, new Array(rangesAtoH.length).fill([])); // initialise with N empty arrays

console.log("grouped", grouped);


// ---letter range I to Q ------------------

const groupedItoQ: Item[][] = sorted.reduce((groups, item) => {
  const firstLetter: string = item.item_text.slice(0,1).toLowerCase();
  console.log(firstLetter);

  // run through each range and check whether the 'firstLetter' fits there
  rangesItoQ.forEach((range, index) => {
    if (firstLetter >= range.first.toLowerCase()
       && firstLetter <= range.last.toLowerCase()) {
      groups[index].push(item);
    }
  });
  return groups;
}, new Array(rangesItoQ.length).fill([])); // initialise with N empty arrays

console.log("grouped I to Q = ", groupedItoQ);


// ---letter range R to Z ------------------

const groupedRtoZ: Item[][] = sorted.reduce((groups, item) => {
  const firstLetter: string = item.item_text.slice(0,1).toLowerCase();
  console.log(firstLetter);

  // run through each range and check whether the 'firstLetter' fits there
  rangesRtoZ.forEach((range, index) => {
    if (firstLetter >= range.first.toLowerCase()
       && firstLetter <= range.last.toLowerCase()) {
      groups[index].push(item);
    }
  });
  return groups;
}, new Array(rangesRtoZ.length).fill([])); // initialise with N empty arrays

console.log("grouped I to Q = ", groupedRtoZ);





  }

Upvotes: 0

This is the solution I came up with. Can be optimised for the cases when we know that the letter ranges don't intersect.

// some basic interfaces to describe types
interface Item {
  item_text: string;
}
interface LetterRange {
  first: string;
  last: string;
}

// the letter ranges
// this solution allows them to intersect
// can adjust for any letter ranges
const ranges: LetterRange[] = [
  {first: 'a', last: 'h'},
  {first: 'i', last: 'q'},
  {first: 'r', last: 'z'}
];


const dropdownList: Item[] = [
  { item_text: 'Organisation' },
  {  item_text: 'EwayBill' },
  {  item_text: 'SAP' },
  {  item_text: 'Collection' },
  {  item_text: 'Cancel' },
  {  item_text: 'Generate' },
  {  item_text: 'Payments' },
  {  item_text: 'SMS' },
  {  item_text: 'Update' }
];

// sort the words alphabetically so that they will appear in the right order
const sorted: Item[] = dropdownList.sort((a,b) => a.item_text.localeCompare(b.item_text));

// array of grouped items (each group is array as well)
const grouped: Item[][] = sorted.reduce((groups, item) => {
  const firstLetter: string = item.item_text.slice(0,1).toLowerCase();
  console.log(firstLetter);

  // run through each range and check whether the 'firstLetter' fits there
  ranges.forEach((range, index) => {
    if (firstLetter >= range.first.toLowerCase()
       && firstLetter <= range.last.toLowerCase()) {
      groups[index].push(item);
    }
  });
  return groups;
}, new Array(ranges.length).fill([])); // initialise with N empty arrays

console.log(grouped);

/*
[ 
  [ { item_text: 'Cancel' },
    { item_text: 'Collection' },
    { item_text: 'EwayBill' },
    { item_text: 'Generate' }
  ],
  [ 
    { item_text: 'Organisation' },
    { item_text: 'Payments' }
  ],
  [ { item_text: 'SAP' },
    { item_text: 'SMS' },
    { item_text: 'Update' }
  ] 
]
 */

Upvotes: 2

Severin Klug
Severin Klug

Reputation: 754

Sort it with a compare function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

dropdownList.sort(function (item1, item2) {
 if (item1.item_text < item2.item_text)
  return -1;
 if ( item1.item_text > item2.item_text)
  return 1;
 return 0;
})

or more simple:

dropdownList.sort(function (item1, item2) {
  return ('' + item1.item_text).localeCompare(item2.item_text);
})

This is copy pasted with changes from https://stackoverflow.com/a/51169/7329611 with credits to Shog9

After sorting you can slice the array into groups with the slice function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice After sorting you should find the indexes of the first occurance of objects with the next higher alphabetical character and set these indexes as slice(from, to) So for the first step you have to find the first element with next higher Character wich in your case is 'i' since its follows 'h'

let breakpoint = dropdownList.find(function(element) {
 return element.item_text.charAt(0).toLowerCase() === 'i';
})

Next you can slice the original array at

let slicePoint = dropdownList.indexOf(breakpoint)-1

dropdownList.slice(slicePoint);

Ofcourse this requires the array to contain at least one element with 'i' at start.

Upvotes: 1

Related Questions