1

I have 2 arrays like so:

var arrayOne = [
    {page:'1',tags:['foo','bar']},
    {page:'2',tags:['oh','boy']}
];
var arrayTwo = [
    {page:'1',tags:['go','out']},
    {page:'9b',tags:['red','blue','green']}
];

I want to compare the two arrays, and if the page property is the same, replace the tags property in arrayOne with the tags property from arrayTwo.

So given the example arrays above, only the tags for page: 1 of arrayOne would get replaced with page: 1's values from arrayTwo.

I'm thinking I can do this with underscore.js, but I'm struggling to see how.

Ideas?

5
  • Are you missing a ' from the final entry in arrayTwo? Is that a typo here, or in your real code? Commented Oct 23, 2012 at 15:07
  • Why do you have arrays of JSON strings? Commented Oct 23, 2012 at 15:07
  • Sorry, been in JSON hell lately, it's just how my brain is stuck, and I'm working with returned data from MongoDB/Mongoose. Yes, just a typo. Commented Oct 23, 2012 at 15:13
  • So are they JSON strings or are they actually unpacked into JavaScript objects? Commented Oct 23, 2012 at 16:29
  • I have edited the original question to fix the JS array syntax. Commented Oct 23, 2012 at 17:29

3 Answers 3

1

If you actually have two arrays of JavaScript objects like this:

var a1 = [
    {page: '1', tags: ['foo', 'bar']},
    {page: '2', tags: ['oh',  'boy']},
    //...
];
var a2 = [
    {page: '1',  tags: ['go', 'out']},
    {page: '9b', tags: ['red', 'blue', 'green']},
    //...
];

Then I'd convert a2 to a page-to-tags lookup table:

var lookup = { }, i, e;
for(i = 0, e = a2[i]; i < a2.length; e = a2[++i])
    lookup[e.page] = e.tags;

and then spin through a1 merging in lookup values as you go:

for(i = 0, e = a1[i]; i < a1.length; e = a1[++i])
    e.tags = lookup[e.page] || e.tags;

Demo: http://jsfiddle.net/ambiguous/aDgH7/

If you must use Underscore, you could replace the loops with _.reduce and _.each:

var lookup = _(a2).reduce(function(lookup, e) {
    lookup[e.page] = e.tags;
    return lookup;
}, { });
_(a1).each(function(e) {
    e.tags = lookup[e.page] || e.tags;
});

Demo: http://jsfiddle.net/ambiguous/rkMZz/

If you could assume a modernish JavaScript, then the standard reduce and forEach array methods could be used:

var lookup = a2.reduce(function(lookup, e) {
    lookup[e.page] = e.tags;
    return lookup;
}, { });
a1.forEach(function(e) {
    e.tags = lookup[e.page] || e.tags;
});

Demo: http://jsfiddle.net/ambiguous/cy2Qy/

If you actually have arrays of JSON strings then you can mix in JSON.parse and JSON.stringify calls to unpack and repack the data.

Sign up to request clarification or add additional context in comments.

Comments

0

like

var arrayOne = [
    '{"page":"1","tags":["foo","bar"]}',
    '{"page":"2","tags":["oh","boy"]}'
];
var arrayTwo = [
    '{"page":"1","tags":["go","out"]}',
    '{"page":"9b","tags":["red","blue","green"]}'
];

var maxLen = Math.max( arrayOne.length, arrayTwo.length ),
    objA, objB;

while( maxLen-- ) {
    objA = JSON.parse( arrayOne[ maxLen ] );
    objB = JSON.parse( arrayTwo[ maxLen ] );

    if( objA.page === objB.page ) {
        objA.tags = objB.tags
        arrayOne[ maxLen ] = JSON.stringify( objA );
    }
}

This is pretty much a perfect world example. It becomes a little bit more tricky if Array one and two do not contain the same amount of items.

3 Comments

They most definitely will not contain the same amount of items.
@k00k: then the above code is unfortunately pretty much useless. In this case you need some unique identifier in both arrays for each entry (this could possibly be the "page" value). So I'd loop over arrayOne and search arrayTwo for a matching entry and if that can be found, replace the "tags" property.
re: looping - yes, that's pretty much what my question is asking, "What's the best way to do? Using Underscore?"
0

I was able to do what I needed by using Underscore's _each by doing one inside of another like so ( http://jsfiddle.net/4JP7g/ ) :

var arrayOne = [
    {page:1,tags:["foo","bar"]},
    {page:2,tags:["oh","boy"]}
];
var arrayTwo = [
    {page:1,tags:["go","out"]},
    {page:9,tags:["red","blue","green"]}
];

_.each(arrayOne, function(one){
    _.each(arrayTwo, function(two){
      if(one.page === two.page){
                one.tags = two.tags;  
                console.log (one.tags);            
      }           
    });
});​

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.