Sort an array of strings with dates

Asked

Viewed 157 times

2

I have the following array:

let datas = ["nov/2018", "set/2018", "jan/2019", "dez/2018", "out/2018"]

when executed

datas.sort()

it orders by alphabetical order, however, I must order first by year and then by alphabetical order.

["dez/2018", "jan/2019", "nov/2018", "out/2018", "set/2018"]

Testing today I arrived at the following line of code:

var datas = ["mar", "abr", "jan", "dez", "set", "mai", "jun", "out", "jul"];
var datas_corretas = ["jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez"];
var result = [];

datas_corretas.forEach(function ordenar(element, index){
  var mes = datas.filter(function(valor){
  return valor == datas_corretas[index];
});
  result.push(mes[0]);
  for(element of result){
    if (element === undefined || element === null){
      result.pop(element);
    }
  }
});
console.log(result);

That way I can sort the data, but the problem is when I use with the year

var datas = ["mar/2018", "abr/2018", "jan/2019", "dez/2018", "set/2018", "mai/2018", "jun/2018", "out/2018", "jul/2018"];

Does anyone have any idea how I can fix this?

2 answers

1


If you want to sort by year and then by month alphabetically and keeping the array in the format you have can do so:

let datas = ["nov/2018", "set/2018", "jan/2019", "dez/2018", "out/2018"];

datas.sort((data1, data2) => {
  const [mes1, ano1] = data1.split('/');
  const [mes2, ano2] = data2.split('/');
  
  return ano1 !== ano2 ? Number(ano2) - Number(ano1) : mes1.localeCompare(mes2);
});

console.log(datas.join("\n"));

Before each comparison between dates he takes the text and divides it into two parts by /, thus obtaining the name of the month and the year. Then if the years are different sort by the year otherwise sort by the month through the locationCompare.

Although the code works, this date format is not ideal and ends up doing a lot more work than usual by splitting the same texts several times.

Edit:

If the ordination by month is not to be alphabetical but by order of the months, that is to say, January is equivalent to 1, February to 2, and so on can do so:

const meses = ["jan", "fev", "mar", "abr", "mai", "jun", "ago", "set", "out", "nov", "dez"];
let datas = ["nov/2018", "set/2018", "jan/2019", "dez/2018", "out/2018"];

datas.sort((data1, data2) => {
  const [mes1, ano1] = data1.split('/');
  const [mes2, ano2] = data2.split('/');
  
  return ano1 !== ano2 ? Number(ano2) - Number(ano1) : meses.indexOf(mes1) - meses.indexOf(mes2);
});

console.log(datas.join("\n"));

Now it took an array of months to know the correct order of months.

Whether the ordering is ascending or descending depends on the order in which you place the variables in the comparisons. When you do Number(ano2) - Number(ano1) has diminishing year but if it does Number(ano1) - Number(ano2) is already increasing. The same principle applies to the months, and therefore reversing to meses.indexOf(mes2) - meses.indexOf(mes1) makes the ordination decreasing of months.

  • I also think it is not the best way to store dates, and I also went to see that this is not only a reusable code, because I tested put the month of abr/2018, and he stood in front of jan/2018

  • @Raphaelmelodelima Isn’t alphabetically the months ? Alphabetically it’s like this in my answer. Is it by month order = January equals to 1 and so on ? If that is so then you have not expressed yourself correctly in the question, nor have you read my answer carefully. But if it is, just say that I edit the answer

  • @Raphaelmelodelima I’ve already edited the answer anyway, so at this point it has both versions.

  • I really expressed myself in a wrong way, I apologize for that and thank you very much for your attention

0

Setting your array to:

<script>
var array = [{id: 1, date: Mar 12 2012 10:00:00 AM}, {id: 2, date: Mar 8 2012 08:00:00 AM}];
</script>

You can get a simple answer like:

<script>
array.sort(function(a,b){
  // Transforme suas strings em datas e subtraia-as
  // para obter um valor que seja negativo, positivo ou zero.
  return new Date(b.date) - new Date(a.date);
});
</script>

Generic and Powerful Response Set a custom nonenumerable sortBy function using a transformation Schwartzian in all arrays:

<script>
(function(){
  if (typeof Object.defineProperty === 'function'){
    try{Object.defineProperty(Array.prototype,'sortBy',{value:sb}); }catch(e){}
  }
  if (!Array.prototype.sortBy) Array.prototype.sortBy = sb;

  function sb(f){
    for (var i=this.length;i;){
      var o = this[--i];
      this[i] = [].concat(f.call(o,o,i),o);
    }
    this.sort(function(a,b){
      for (var i=0,len=a.length;i<len;++i){
        if (a[i]!=b[i]) return a[i]<b[i]?-1:1;
      }
      return 0;
    });
    for (var i=this.length;i;){
      this[--i]=this[i][this[i].length-1];
    }
    return this;
  }
})();
</script>

Use like this:

<script>
array.sortBy(function(o){ return o.date });
</script>

If your date is not directly comparable, make a comparable date, for example:

<script>
array.sortBy(function(o){ return new Date( o.date ) });
</script>

You can also use this to sort by multiple criteria, if you return an array of values:

<script>
// Classificar por data e pontuar (invertido), então o nome
array.sortBy(function(o){ return [ o.date, -o.score, o.name ] };
</script>

Behold http://phrogz.net/JS/Array.prototype.sortBy.js for more details.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.