1

I've been trying to figure out how to do recursion for 2 objects that have similar properties, but also have differences. I need to merge these 2 objects in a unique way, so there are no duplicate countries or models etc.

EDIT: in vanilla js only please

var us1 = {
  country: {
    "United States": {
      "Ford": {
        "engine": {
          type1: "4 cyl",
          type2: "6 cyl"
        }
      },
      "Chevy": {
        "engine": {
          type1: "6 cyl"
        }
      }
    }
  }
}

var us2 = {
  country: {
    "United States": {
      "Ford": {
        "engine": {
          type3: "12 cyl"
        }
      },
      "Saturn": {
        "engine": {
          type1: "4 cyl"
        }
      }
    }
  }
}

var cars = [us1, us2];
var newCars = [];

function fn(cars) {
  if (typeof cars == "object") {
    for (var attr in cars) {
      if (!newCars.hasOwnProperty(cars[attr])) {
        newCars.push(cars[attr]);
      }

      fn(cars[attr])
    }
  } else {
    //
  }
}

console.log(fn(cars));
console.log(newCars)

Result wanted: var us1 = { country: { "United States": { "Ford": { "engine": { type1: "4 cyl", type2: "6 cyl", type2: "12 cyl" } }, "Chevy": { "engine": { type1: "6 cyl" } }, "Saturn": { "engine": { type1: "4 cyl" } } } } }

Tatarin
  • 1,238
  • 11
  • 28

3 Answers3

1

If you don't want to use a library, it's trivial to write yourself. Something along the lines of

// (to: Object, ...sources: Object[]) => Object
function mergeDeep(to) {
  const sources = Array.from(arguments).slice(1)

  // (to: Object, from: Object) => void
  const _merge = (to, from) => {
    for (let a in from) {
      if (a in to) {
        _merge(to[a], from[a])
      } else {
        to[a] = from[a]
      }
    }
  }

  sources.forEach(from => {
    _merge(to, from)
  })

  return to
}

See demo here https://tonicdev.com/bcherny/mergedeep

But really, you should be using a library for this. Writing it yourself is guaranteed to be buggier and slower than any widely used existing implementation.

bcherny
  • 3,072
  • 2
  • 27
  • 35
  • @jfriend00 I'm not sure we're looking at the same code.. OP doesn't seem to have `4 6 cyl` anywhere. – bcherny Apr 21 '16 at 01:15
0

Using lodash:

_.merge(us1, us2)
bcherny
  • 3,072
  • 2
  • 27
  • 35
  • is there a way to do it only in vanilla JS? – Tatarin Apr 21 '16 at 00:25
  • technically this works in lodash, but i dont want to add lodash just for this functionality, ill still +1 for working answer – Tatarin Apr 21 '16 at 00:36
  • @jfriend00 it was fault on my behalf I comma separated them, I also updated the question right away. Sorry about that, didnt mean to confuse you guys. I still need that obj to be deep merged together, but only in vanilla js. I appreciate you looking into this issue, hoping I can still get an answer. – Tatarin Apr 21 '16 at 00:50
-2

If you are open to use underscore.js, the following should work:

_.extend(us1, us2)
ryan
  • 974
  • 2
  • 7
  • 13