IntricatePixels
IntricatePixels

Reputation: 1229

Javascript: find match in array of objects and move to first position

What I"m trying to accomplish is similar to the PHP solution from this other post on Stackoverflow, but with JavaScript:

Multidimensional array, find item and move to the top?

I'm returning an object with the following:

 $.get(uri, function (data) {

    self.options = [];

    $.each(data, function (index, item) {
        self.options.push(item);
    });
 });

self.options[] looks something like:

   Object 1: 
          Id: "1"
          Name: "Bill"
   Object 2: 
          Id: "2"
          Name: "Sarah"
   Object 3: 
          Id: "3"
          Name: "Mike"

I need to find "Sarah" in the array object and move it up to be the first item of the array. How can I accomplish this?*

Upvotes: 1

Views: 8066

Answers (4)

Nikhil Mahirrao
Nikhil Mahirrao

Reputation: 3721

You can use the sort method of array

var array = ['apple','zebra','cherry','grap'];

// 'zebra' at first index of array
array.sort( (first, second) => {
  if(first === 'zebra') return -1;
});
console.log('first', array);

// 'zebra' at last index of array
array.sort( (first, second) => {
  if(second === 'zebra') return -1;
});
console.log('last', array);

Upvotes: 1

user663031
user663031

Reputation:

You can literally write out the English description of your problem in JavaScript.

array.unshift(                      // add to the front of the array
  array.splice(                     // the result of deleting items
    array.findIndex(                // starting with the index where
      elt => elt.Name === 'Sarah'), // the name is Sarah
  1)[0]                             // and continuing for one item
)

Or, more compactly:

array.unshift(array.splice(array.findIndex(elt => elt.Name === 'Sarah'), 1)[0])

findIndex is not supported in Internet Explorer at all so to support IE 11 you can use a combination of map (Since IE 9) and indexOf (Since IE 8) - This gives you full, non-ever green, cross browser compatibility.

array.unshift(                      
  array.splice(                     
    array.map(function(e){ return e.Name}).indexOf('Sarah'), 
  1)[0]                             
)

But that doesn't handle the case where Sarah is missing, or there is more than one Sarah. A more general solution would be to split the incoming array into two, based on some condition, then recombine them. That's what this tee function does:

function tee(a, fn) {
  var non_matches = [];
  var matches = a.filter(function(e, i, a) {
    var match = fn(e, i, a);
    if (!match) non_matches.push(e);
    return match;
  });
  return matches.concat(non_matches);
}

Now, in ES6, you can obtain your result with

tee(a, e => e.Name === 'Sarah')

Or for older browsers, with ES5:

tee(a, function(e) { return e.Name === 'Sarah'; })

Upvotes: 14

choz
choz

Reputation: 17888

You can use Array.prototype.sort to accomplish this.

E.g.

var arr = [];
arr.push({Id:"1", Name:"Bill"});
arr.push({Id:"2", Name:"Sarah"});
arr.push({Id:"3", Name:"Mike"});

arr.sort(function(first, second) {
  if (second.Name == "Sarah") return 1;
});

console.log(arr);
// [Object { Id="2",  Name="Sarah"}, Object { Id="1",  Name="Bill"}, Object { Id="3",  Name="Mike"}]

Or another alternative one,

var arr = [];
arr.push({Id:"1", Name:"Bill"});
arr.push({Id:"3", Name:"Mike"});
arr.push({Id:"2", Name:"Sarah"});

function getIndexByName(name) {
    for(var i = 0; i < arr.length; i++) {
        if (arr[i].Name == name) {
            return i;
        }
    }
}

var pos = getIndexByName("Sarah");
arr.splice(0, 0, arr[pos++]) // Insert Sarah at `arr` first position
arr.splice(pos, 1); // Remove old Sarah

Upvotes: 4

joemillervi
joemillervi

Reputation: 1067

Here is one way to do what you are asking.

$.get(uri, function (data) {

   self.options = [];
   var chosenName = 'Sarah'
   var tmp = [];
   $.each(data, function (index, item) {
       // if we find it while iterating through do not add it, store it it tmp
       if (item.Name === chosenName) {
          tmp.push(item);
       } else {
          self.options.push(item);
       }
   });
   // if we found it push it to the front of the array
   if (tmp.length > 0) self.options = tmp.concat(self.options)
});

Upvotes: -1

Related Questions