Home > Blockchain >  How can I sort these arrays efficiently?
How can I sort these arrays efficiently?

Time:01-25

I am trying to find a logic in sorting some arrays, but after hours of brainstorming it's just beyond me and probably you have an idea

Let's say we have an array of objects. The Objects looks like this:

let obj = {day:'2',month:'6',year:'1938' }

and the array will look like this

let array = [ {year:'1938, month:'6', day:'3'},{year:'1935', month:'5', day:'3'},{year:'1935, month:'', day:''}, {year:'1935', month:'5', day:''}, {year:'1934}, month:'3', day:''}, {year:'1934', month:'3', day:'15'}, {year:'1934}, month:'', day:''}];

and I want that the sorted array would look something like

let sortedArray = [{year:'1934}, month:'', day:''},{year:'1934}, month:'3', day:''},{year:'1934}, month:'3', day:'15'},{year:'1935, month:'', day:''},{year:'1935', month:'5', day:''},{year:'1935', month:'5', day:'3'},{year:'1938, month:'6', day:'3'}

The fields for year, month and day are not required because in my app probably someone know an estimate year when something happened and it's not mandatory, but when I display all the objects and I want them to start with all the objects that only have the year (sorted), then all the objects that have the year and the month (sorted by year and month), and then all the objects that have all 3. But also sorted chronologically. What I am building is a timeline. Also you cannot add only year and day and year is mandatory.

I tried building 3 arrays which: 1 which holds the objects with only years, then 1 which hold years and months, and one with all 3 of them.

something like

let array = [ {year:'1938, month:'6', day:'3'},{year:'1935', month:'5', day:'3'}, {year:'1935, month:'', day:''}, {year:'1935', month:'5', day:''}, {year:'1934}, month:'3', day:''}, {year:'1934', month:'3', day:'15'}, {year:'1934}, month:'', day:''}];

let array1 = [];
let array2 = [];
let array3 = [];

array.forEach((element) => {

if(element.month === '' && element.day ==='') 
    array1.push(element)
if(element.month !== '' && element.day ==='') 
    array2.push(element)
if(element.month !== '' && element.day !=='') 
    array3.push(element)

});

// I sorted array1 because they hold the years;

array1.sort(function(a,b) {
    if(Number(a.year)>Number(b.year)) return 1;
    if(Number(a.year)<Number(b.year)) return -1;
    return 0;
});

let currentYear;
let currentYearIndex;

for(let i = 0;i< array1.length; i  } {

    if(array1[i] !== array1[i 1] {
        currentYear = array[i].year; 
        currentYearPosition=i}

    }
    for(let j = 0;j< array2.length; j  } {

        if(array2[j] === currentYear){}

    }

and here my logic died because I had to do another if to check if the month is less or greater that what we already have in the first array but we didn't at the beginning. I don't know if I tried to reinvent the wheel or not. If exists a solution to sort my array that way I would appreciate your help. Thank you!

CodePudding user response:

You could try filter to groups and then converting them each to a date, and then perform the sort on each group.

There is scope to improve this code.

const array = [
  {year:'1938', month:'6', day:'3'},
  {year:'1935', month:'5', day:'3'}, 
  {year:'1935', month:'', day:''}, 
  {year:'1935', month:'5', day:''}, 
  {year:'1934', month:'3', day:''}, 
  {year:'1934', month:'3', day:'15'}, 
  {year:'1934', month:'', day:''}
];

const yearSort = array => {
  return array.filter(item => item.year && !item.month && !item.day).map(item => { 
    return {
      item,
      date: new Date(parseInt(item.year),0,1)
    }
  }).sort((a,b) => a.date < b.date ? -1 : 1)
      .map(i => i.item)
}

const yearMonthSort = array => {
  return array.filter(item => item.year && item.month && !item.day).map(item => { 
    return {
      item,
      date: new Date(parseInt(item.year),item.month - 1,1)
    }
  }).sort((a,b) => a.date < b.date ? -1 : 1)
      .map(i => i.item)
}

const yearMonthDaySort = array => {
  return array.filter(item => item.year && item.month && item.day).map(item => { 
    return {
      item,
      date: new Date(parseInt(item.year),item.month - 1,parseInt(item.day))
    }
  }).sort((a,b) => a.date < b.date ? -1 : 1)
      .map(i => i.item)
}


const sorted = yearSort(array)
                .concat(yearMonthSort(array))
                  .concat(yearMonthDaySort(array))

console.log({ sorted });

CodePudding user response:

In your sort compare function, first check year, when same check month and when same check for day.

  1. Convert all values to number and compare.
  2. '' will be 0 (when converting to number from string using operator)

const array = [
  { year: "1938", month: "6", day: "3" },
  { year: "1935", month: "5", day: "3" },
  { year: "1935", month: "", day: "" },
  { year: "1935", month: "5", day: "" },
  { year: "1934", month: "3", day: "" },
  { year: "1934", month: "3", day: "15" },
  { year: "1934", month: "", day: "" },
];

array.sort((a, b) => {
  if (a.year === b.year) {
    if (a.month === b.month) {
      return  a.day -  b.day;
    }
    return  a.month -  b.month;
  }
  return  a.year -  b.year;
});

console.log(array);

  • Related