Dan The Man
Dan The Man

Reputation: 1895

sort 2 array with the values of one of them in javascript

i have two array, lets say priceArray= [1,5,3,7]

userIdArray=[11, 52, 41, 5]

i need to sort the priceArray, so that the userIdArray will be also sorted. for example the output should be:

priceArray= [1,3,5,7] userIdArray=[11, 41, 52, 5]

any ideas how to do it?

i am writing my server in NodeJS

Upvotes: 3

Views: 133

Answers (4)

Nina Scholz
Nina Scholz

Reputation: 386634

Taken from Sorting with map and adapted for the userIdArray:

// the array to be sorted
var priceArray = [1, 5, 3, 7],
    userIdArray = [11, 52, 41, 5];

// temporary array holds objects with position and sort-value
var mapped = priceArray.map(function (el, i) {
    return { index: i, value: el };
});

// sorting the mapped array containing the reduced values
mapped.sort(function (a, b) {
    return a.value - b.value;
});

// container for the resulting order
var resultPrice = mapped.map(function (el) {
    return priceArray[el.index];
});
var resultUser = mapped.map(function (el) {
    return userIdArray[el.index];
});

document.write('<pre>' + JSON.stringify(resultPrice, 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(resultUser, 0, 4) + '</pre>');

With proper data structure, as rrowland suggest, you might use this:

var data = [{
        userId: 11, price: 1
    }, {
        userId: 52, price: 15
    }, {
        userId: 41, price: 13
    }, {
        userId: 5, price: 17
    }];

data.sort(function (a, b) {
    return a.price - b.price;
});

document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');

A bit shorter with ES6

var priceArray = [1, 5, 3, 7],
    userIdArray = [11, 52, 41, 5],
    temp = Array.from(priceArray.keys()).sort((a, b) => priceArray[a] - priceArray[b]);

priceArray = temp.map(i => priceArray[i]);
userIdArray = temp.map(i => userIdArray[i]);

console.log(priceArray);
console.log(userIdArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 4

HMR
HMR

Reputation: 39270

I have seen a nice talk about making impossible state impossible. This covered the 2 arrays that are related but can go out of sync and better to use one array of objects that have 2 properties (as mentioned several times).

However; if you want to mutate both arrays and sort them the same way you can do the following:

//this will mutate both arrays passed into it
//  you could return the arrays but then you need to do arr.slice(0).sort(...) instead
const sortSame = sortFn => (arrayToSort,arrayToSortSame) => {
  const sortResults = [];
  arrayToSort.sort(//will mutate the array
    (a,b)=>{
      const result = sortFn(a,b);
      sortResults.push(result);
      return result
    }
  );
  arrayToSortSame.sort(()=>sortResults.shift());
  return undefined;
}

const priceArray= [1,5,3,7];
const userIdArray=[11, 52, 41, 5];
const numSortSameAscending = sortSame((a,b)=>a-b);
numSortSameAscending(priceArray,userIdArray);
console.log(
  priceArray,userIdArray
)

Even though the code in this answer may look simpler it is not the cheapest way to do it, as mapping is a cheaper operation than sorting (better to map 3 times and sort once then to sort twice) depending on the size of the arrays and how much the original array is out of order this way of sorting same may be very expensive.

Upvotes: 0

Joshua Comeau
Joshua Comeau

Reputation: 2753

Building on Rrowland's answer, you can create the array of objects with a library like lodash:

var prices  = [1, 5, 8, 2];
var userIds = [3, 5, 1, 9];

var pairs = _.zipWith(prices, userIds, function(p, u) {
  return { price: p, userId: u };
}); 

This will give you an object like:

[ 
  { price: 1, userId: 3 },
  { price: 5, userId: 5 },
  ... etc
]

Then, for sorting, you can simply use a Javascript sort:

pairs.sort(function(p) { return p.price });

If you really need it as an array of userIds, you can get it back, after the sort:

var sortedUserId = pairs.map( function(p) { return p.userId });
// returns [ 3, 9, 5, 8 ];

Upvotes: 0

rrowland
rrowland

Reputation: 2814

It's hard to prescribe a better solution without knowing the whole use-case. That said, if you need these sorted by ID, it may make more sense to create a single array that contains user objects:

var users = [
  { id: 123, price: 25.00 },
  { id: 124, price: 50.00 }
];

users.sort(function(a, b) {
  return a.id - b.id;
});

Or, if they don't need to be sorted, you can simply create a map of users by id:

var userPrices = {
  123: 25.00,
  124: 50.00
};

Upvotes: 0

Related Questions