3

So I have an array of objects ex:

var a = {user: [
 {year:'1950',name:'Joe'},
 {year:'19XX',name:'Chris'},
 {year:'1980',name:'Bob'},
 {year:'1955',name:'Jan'}
]}

I use this data to template out simple elements holding the year and name. I also have option via a select element to sort this data and then use the sorted to template it out again in order of sort. (bob,chris,jan,joe) or year. But my issue starts with year.

I am needing to continue to use a simple plugin jsonQ (http://ignitersworld.com/lab/jsonQ.html) to edit and sort data, and need to have data for year actually be a little different than desc or asc.

1st I need to edit data at various parts, like year (19XX should become 'Pre 1950'):

//inside ajax success function
var dataObj = jsonQ(data);

dataObj.find('year').value(function (data){
   if (data == '19XX') {
       return 'pre 1953'
   } else {
       return data;
   }
});

Now I will have a final product data set that needs to be sorted.

var orderedData = dataObj.sort('year', {'order' : 'ASC'});  

But this gives me the data back as:

{
 user: [
  {year:'1950',name:'Joe'},
  {year:'1955',name:'Jan'},     
  {year:'1980',name:'Bob'},
  {year:'Pre 1950',name:'Chris'}
 ]
}

What I need is the data to be returned as:

{
 user: [
  {year:'Pre 1950',name:'Chris'},
  {year:'1950',name:'Joe'},
  {year:'1955',name:'Jan'},     
  {year:'1980',name:'Bob'}
 ]
}

Any suggestions?

1
  • 1
    You need to define your own compairing function. Actually P is lexicographically bigger than any digit. Commented Jan 6, 2017 at 19:18

3 Answers 3

2

Well, you can implement your own sorting criterion, and pass it to Array.sort().

This criterion takes the form of a function(a, b) that returns a number:

  • Negative if a should go before b in the sorted list
  • Zero if a and b are essentially equal
  • Postive if a should go after b

This may look pretty arbitrary, but think about it this way: in the simple case of sorting numbers from lesser to greater, the function returns a - b. So, f(a, b) is a - b, and a - b < 0 means a < b.

Back to your case. Let's implement a criterion function that sorts the years from lesser to greater, putting Pre 1950 at the top:

function byYear(a, b) {
  if (a === "Pre 1950") return -1 // a goes before
  if (b === "Pre 1950") return 1  // b goes before

  return parseInt(a) - parseInt(b) // lesser goes before
})

Try it in the browser console:

> ["1980", "1970", "Pre 1950"].sort(byYear)
["Pre 1950", "1970", "1980"]

Given that you're sorting objects, you'll need to adapt the criterion function above to work with a.year and b.year.

Sign up to request clarification or add additional context in comments.

3 Comments

The if (a === "Pre 1950") return -1; part is not necessary.
I guess you have a point. +1 for the detailed answer. Great job.
@slezica - Yea, +1 this is a great answer for understanding this kind of manipulation .. I was stuck with this plugin specifically.
0

You could sort the array in three steps

  • sort priority years, like 19XX
  • sort by years without priority
  • sort by name.

var a = { user: [{ year: '1950', name: 'Joe' }, { year: '19XX', name: 'Chris' }, { year: '1980', name: 'Bob' }, { year: '1955', name: 'Jan' }] };

a.user.sort(function (a, b) {
    var order = { '19XX': -1 };
    return (order[a.year] || 0) - (order[b.year] || 0) || a.year - b.year || a.name.localeCompare(b.name);
});

console.log(a);

Comments

0

I have just found the solution, shortly after posting, while using the plugin. (which is what I wanted, Sorry, I should have specified that more).

My problem was in my options passed into the plugin's sort()method. not easy to find since documentation isn't 100.

var orderedData = dataObj.sort('year', {
  'order' : 'ASC',
  logic: function(val){
     return (val == 'pre 1950') ? '1911' : val;
  }
});

What this is essentially doing is replacing 'pre 1950' with 1911, just for sorting purposes.

2 Comments

you could skip paranteses around the condition.
@NinaScholz - you are right .. old habits die hard :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.