Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order an array of words based on another array of words [duplicate]

I have an array like this:

unorderedArr = ['pear', 'apple', 'banana', 'peach', 'pineapple'];

I would like to order this array based on a other given array like this:

order = ['peach', 'apple', 'pineapple']

The preferred result would be:

orderedArr = ['peach', 'apple', 'pineapple', 'banana', 'pear'];

It doesn't matter on what index the words that are not in the order array are placed. It's not guaranteed that the words in the order array will be in the unordered array

Current Code Solution

I tried using a switch statement like this:

const orderedArr = []
unorderedArr.forEach(word => {
  switch (word) {
    case 'peach':
      orderedArr.push(word);
      break;

    case 'apple':
      orderedArr.push(word);
      break;

    case 'pineapple':
      orderedArr.push(word);
      break;

    default:
      orderedArr.push(word);
      break;
    }
});

But I found out that a switch statement doesn't check on the first case first.

like image 586
Stijn Avatar asked Dec 19 '18 14:12

Stijn


3 Answers

I don't think there's an easy non-programmatic way of doing this. What you need is an algorithm that yields the desired result, like this:

function partialOrder(preferences, data)
{
  var result, reminder;

  result = [];

  // find preferences and put them into result
  preferences.forEach((name) => {
    result = result.concat(
      data.filter((d) => d.name === name)
    );
  });

  // find remaining data not in preferences
  reminder = data.filter((item) =>
    preferences.indexOf(item.name) === -1
  );

  return result.concat(reminder);
}

var preferences = [ "peach", "pear", "pineapple", "<alien-fruit>" ];
var data = [
  { "name": "apple", "image_url": "xApple" },
  { "name": "pineapple", "image_url": "xPineapple" },
  { "name": "peach", "image_url": "xPeach" },
  { "name": "pear", "image_url": "xPear" },
  { "name": "banana", "image_url": "xBanana" }
];

console.log(partialOrder(preferences, data));
like image 98
pid Avatar answered Nov 09 '22 23:11

pid


You could take an object for the sort order and a default value for items who have not an order.

var array = ['pear', 'apple', 'banana', 'peach', 'pineapple'],
    wanted = ['peach', 'apple', 'pineapple'],
    order = Object.assign({ default: Infinity }, ...wanted.map((v, i) => ({ [v]: i + 1 })));
    
array.sort((a, b) => (order[a] || order.default) - (order[b] || order.default));

console.log(array);
like image 27
Nina Scholz Avatar answered Nov 10 '22 00:11

Nina Scholz


Try this with simple logic;

var finalArray = [];

//loop over order array
for(var i=0; i<order.length; i++)   
{             
   //if order array element present into un-order array push in new array
   //this will ensure that in finalArray elements stays in order                  
   if(unordedArr.indexOf(order[i]) > -1)
       finalArray.push(order[i]);                                    
}

//loop over un-order array
for(var i=0; i<unordedArr.length; i++)    
{                    
   //if in final array the element is not present then enter it again  
   //which means the rest of the elements need to inserted
   if(finalArray.indexOf(unordedArr[i]) == -1)
   {
        finalArray.push(unordedArr[i]);  
   }
}                            

console.log(finalArray)
like image 20
KOUSIK MANDAL Avatar answered Nov 10 '22 00:11

KOUSIK MANDAL