4

I have an object, let's say

var obj = [{"name": "banana", "type": "fruit"},
           {"name": "carrot", "type": "vegetable"}];

And I need to add an object right after the first one [0] so I'll get the following:

var obj = [{"name": "banana", "type": "fruit"},
           {"name": "apple", "type": "fruit"},
           {"name": "carrot", "type": "vegetable"}];

needless to say I want it dynamic, and I'm trying to avoid loops for ease of use later down the road...

Is there any function like

obj.pushAfter(this['type'], "fruit", {"name": "apple", "type": "fruit"});

Type of function? P.S I'm using Jquery so that's an option

gal zakay
  • 105
  • 1
  • 9

5 Answers5

2

While the accepted answer is informative and leads you to the right direction, if you are actually in need if a pushAfter function that does exactly what you described, you could roll your own like so...

function pushAfter(coll, k, v, add) {
  var matchIndex = coll.reduce(function(prevVal, currVal, i, arr) {
    if (currVal[k] === v) {
      return i;
    }
  });

  coll.splice(matchIndex + 1, 0, add);
}

var obj = [{"name": "banana", "type": "fruit"},
           {"name": "carrot", "type": "vegetable"}];

pushAfter(obj, 'type', "fruit", {"name": "apple", "type": "fruit"});
pushAfter(obj, 'name', "carrot", {"name": "radish", "type": "vegetable"});

This would yield:

[{
  name: "apple",
  type: "fruit"
}, {
  name: "banana",
  type: "fruit"
}, {
  name: "carrot",
  type: "vegetable"
}, {
  name: "radish",
  type: "vegetable"
}]

This finds your specified key and value within the given collection and splices in the new item at the matched index. Leveraging reduce in this case also provides a simple way to identify the match's index. Additionally, here's a working example.

Seth
  • 10,198
  • 10
  • 45
  • 68
  • That's simply amazing! just learned a lot from this comment, thank you very much! – gal zakay May 20 '16 at 13:36
  • I'm happy to help. Let me know if you try it out and how it works out. Also, as @tpdietz pointed out, if you find this helpful then it's great for the community if you upvote it :D – Seth May 20 '16 at 13:38
1

First off, your talking about pushing into an array, not an object. The two are different animals, and it's important you understand their differences.

What you want is the splice function on the native array object. arr.splice(index, 0, item); will insert item into arr at the specified index.

Source: How to insert an item into an array at a specific index?

Documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

Community
  • 1
  • 1
tpdietz
  • 1,358
  • 9
  • 17
1
var obj = [{"name": "banana", "type": "fruit"},
           {"name": "carrot", "type": "vegetable"}];

// splice(position, numberOfItemsToRemove, item)
obj.splice(1, 0, {"name": "apple", "type": "fruit"});
Shantanu Madane
  • 617
  • 5
  • 14
0

You could a function for it. It searches for the right property key and insert the item after the group, before other groups have started.

This solution features Array#some, because it stops iterating if the wanted index is found.

function pushAfter(array, key, item) {
    var index = 0;
    array.some(function (a, i) {
        if (a[key] === item[key]) {
            index = i + 1;
            return false;
        }
        return index;
    });
    array.splice(index, 0, item);
}

var array = [{ "name": "banana", "type": "fruit" }, { "name": "carrot", "type": "vegetable" }];
pushAfter(array, 'type', { "name": "apple", "type": "fruit" });

console.log(array);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

Doing a sorted push will only work if the array is already sorted correctly, so if you always start with an empty or sorted array and the array is only mutated by the pushAfter function, then you're fine. However, if you retrieve the array from an external API, it can be modified outside of your pushAfter function, or you are otherwise unable to guarantee that the array will always be sorted before you push to it, you can't guarantee that a pushAfter function will always provide a sorted array.

For example, if you start with an array with objects sorted in the order of fruit, fruit, vegetable, fruit, the above pushAfter function will result in the array sorted as fruit, fruit, vegetable, fruit, fruit instead of fruit, fruit, fruit, fruit, vegetable. A method that will always be reliable would be to do a regular push and then sort the array.

function sortedPush(sourceArray, newObject) {
  sourceArray.push(newObject);

  sourceArray.sort(function(a, b) {
 // returns 0 if both objects have equal type
 //         1 if a is greater than b (should be sorted after)
 //        -1 if a is less than b (should be sorted before)
 return (a.type === b.type) ? 0 : a.type > b.type;
  });
}

var unsortedArray = [{
  "name": "banana",
  "type": "fruit"
}, {
  "name": "carrot",
  "type": "vegetable"
}, {
  "name": "grape",
  "type": "fruit"
}];

sortedPush(unsortedArray, {
  "name": "orange",
  "type": "fruit"
});

console.log(unsortedArray);

unsortedArray after the sorted push:

[{
  name: "banana",
  type: "fruit"
},  {
  name: "grape",
  type: "fruit"
},  {
  name: "orange",
  type: "fruit"
},  {
  name: "carrot",
  type: "vegetable"
}]

Demo

See documentation for Array.sort

Michael L.
  • 620
  • 3
  • 17