0

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' }
]
James Z
  • 12,209
  • 10
  • 24
  • 44
Techdive
  • 997
  • 3
  • 24
  • 49

3 Answers3

2

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' }
  ] 
]
 */
1

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.

Severin Klug
  • 733
  • 5
  • 9
0

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);





  }
Techdive
  • 997
  • 3
  • 24
  • 49
  • Hmm.. Why did you decide to triple the size of the code I suggested? The point was that you have an array of ranges: [RangeAtoH, RangeItoQ, RangeRtoZ]. With the code I've shown you get the output of wordGroups: [WordsInRangeAtoH, WordsInRangeItoQ, WordsInRangeRtoZ]. This works out of the box. No need to change anything. You can output each group simply by accessing wordGroups array. console.log("grouped A to H = ", wordGroups[0]); console.log("grouped I to Q = ", wordGroups[1]); console.log("grouped R to Z = ", wordGroups[2]); – Daniil Andreyevich Baunov Nov 17 '18 at 09:52
  • No you don't get . All the three arrays have all the values arranged alphabetically. That is why i segregated. Thanks a lot anyway! You solved it originally. – Techdive Nov 17 '18 at 10:54