Exception
Exception

Reputation: 8389

rearrange Array according to values order of another Array

I have two arrays like below

  var arr = ["x", "y", "z", "a", "b", "c"];
  var tgtArr = [{val:"a"}, {val:"b"}]; It does not need to be as lengthy as Array `arr`

This is what I have tried

  var dest = new Array(arr.length);
  for(var i = 0; i < arr.length; i++){
      for(var k = 0; k < tgtArr.length; k++){
          dest[i] = dest[i] || [];
          if(tgtArr[k].val == arr[i]){
              dest[i] = arr[i];
          }
      }
  }
  console.log(dest);

My Expected output is (for above tgtArr value)

  [{}, {}, {}, {val:"a"}, {val:"b"}, {}];

if tgtArr is empty Array

  [{},{},{},{},{},{}]      

Here is the fiddle. Any alternative for this, it seems not a good way to me as I am iterating through the entire array everytime.

Upvotes: 0

Views: 82

Answers (5)

Paul Draper
Paul Draper

Reputation: 83393

Short:

var result = arr.map(function(x) {
    return tgtArr.some(function(o) { return o.val == x; }) ? {val:x} : {};
});

This is more efficient:

var set = {};
tgtArr.forEach(function(obj, i) {
    set[obj.val] = true;
});
var result = arr.map(function(x) {
    return x in set ? {val:x} : {};
});

Upvotes: 2

RobG
RobG

Reputation: 147503

This is the same as Paul's answer, but with a loop instead of map. It collects the keys first based on the val property, then creates a new array either with empty objects if the key isn't in tgtArr, or copies a reference to the object from tgtArr if it is:

function newArray(arr, tgtArr) {
  var keys = {},
      i = tgtArr.length,
      j = arr.length,
      newArr = [];

  // Get keys
  while (i--) keys[tgtArr[i].val] = tgtArr[i];

  // Make new array
  while (j--) newArr[j] = arr[j] in keys? keys[arr[j]] : {};

  return newArr; 
}

It should be efficient as it only traverses each array once.

Upvotes: 1

charlietfl
charlietfl

Reputation: 171690

var tmp = {};
for (var i = 0; i < tgtArr.length; i++) {
    tmp[tgtArr[i].val] = i;
}

var dest = [];

for (var i = 0; i < arr.length; i++) {
    var obj= tmp[arr[i]] === undefined ? {} : tgtArr[tmp[arr[i]]];
    dest.push(obj);     

}

DEMO

Upvotes: 1

McGarnagle
McGarnagle

Reputation: 102793

I like using map rather than loops for this kind of thing (Fiddle):

var result = arr.map(function(x) {
    var match = tgtArr.filter(function(y) {
        return y.val == x;
    });
    if (match.length == 1) return match[0];
    else return {};
});

This is a possibly inefficient, in that it traverses tgtArr for every item in arr, so O(n*m). If needed, you could fix that by pre-processing tgtArr and converting it to a hash map (Fiddle). This way you've got an O(n+m) algorithm (traverse each array once):

var tgtMap = {};
tgtArr.forEach(function(x) { tgtMap[x.val] = x; })
var result = arr.map(function(x) {
    var match = tgtMap[x];
    return match || {};
});

Upvotes: 1

donkeydown
donkeydown

Reputation: 708

var dest = new Array(arr.length);
  for(var i = 0; i < arr.length; i++){
      dest[i] = {}
      for(var k = 0; k < tgtArr.length; k++){
          if(tgtArr[k].val == arr[i]){
              dest[i] = tgtArr[k];
          }
      }
  }
  console.log(dest);

Upvotes: 1

Related Questions