2

I have an object as follows

[
    {
        "config": {
            "holes": 18
        }
    },
    {
        "config": {
            "single_cart": false
        }
    },
    {
        "config": {
            "shared_cart": false
        }
    },
    {
        "config": {
            "caddie": false
        }
    },
    {
        "config": {
            "transfers": false
        }
    },
    {
        "config": {
            "meals": false
        }
    },
    {
        "config": {
            "all_inclusive": false
        }
    }
]

which i am trying to convert into

{
   "config":{
      "holes":18,
      "single_cart":false,
      "shared_cart":false,
      "caddie":false,
      "transfers":false,
      "meals":false,
      "all_inclusive":false
   }
}

This is an example 'merge' as these could be of any name and value key. I have tried and failed to use reduce, map, foreach and can never join them together as such.

If someone can help point me in the right direction that would be amazing. All the examples i have seen refer to specifically named keys to do the merge using object.assign etc..

3
  • Could "config" be named anything or just the properties within? Commented Sep 15, 2022 at 17:04
  • Config can be named Anything, so i don't think everyone read the last paragraph of my request Commented Sep 16, 2022 at 8:14
  • I've posted an answer that should work without knowing any of the keys (including "config") in advance. Let me know if it does the trick or not. Commented Sep 16, 2022 at 18:36

4 Answers 4

1

Here is a way to do it without knowing any of the keys in advance.

const input = [
  {
    "config": {
      "holes": 18
    }
  },
  {
    "config": {
      "single_cart": false
    }
  },
  {
    "config": {
      "shared_cart": false
    }
  },
  {
    "config": {
      "caddie": false
    }
  },
  {
    "config": {
      "transfers": false
    }
  },
  {
    "config": {
      "meals": false
    }
  },
  {
    "config": {
      "all_inclusive": false
    }
  }
];

const mergeObjects = (a, b) => {
  for (let k in b) {
    if (k in a) {
      if (typeof(a[k]) === 'object' && typeof(b[k]) === 'object') {
        a[k] = mergeObjects(a[k], b[k]);
      } else {
        throw `Unable to merge because key "${k}" is in both objects (and not both values are objects).`;
      }
    } else {
      a[k] = b[k];
    }
  }

  return a;
};

const output = input.reduce(mergeObjects, {});

console.log(output);

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

Comments

1

You can use reduce() to merge all the objects in the array. You can use ... spread syntax to combine objects.

const data = [{
    "config": {
      "holes": 18
    }
  },
  {
    "config": {
      "single_cart": false
    }
  },
  {
    "config": {
      "shared_cart": false
    }
  },
  {
    "config": {
      "caddie": false
    }
  },
  {
    "config": {
      "transfers": false
    }
  },
  {
    "config": {
      "meals": false
    }
  },
  {
    "config": {
      "all_inclusive": false
    }
  }
];

const result = {
  config: data.reduce((acc, obj) => ({...acc, ...obj.config}), {})
};

console.log(result);

2 Comments

This would work if i knew the dimensions of the object each time.
I thought you were referring to the nested keys like holes and single_cart. I assumed config was known, since it's consistent throughout the example.
0

I created a codepen here

which does what you were looking for in a fairly simple way.

const data = [
    {
        "config": {
            "holes": 18
        }
    },
    {
        "config": {
            "single_cart": false
        }
    },
    {
        "config": {
            "shared_cart": false
        }
    },
    {
        "config": {
            "caddie": false
        }
    },
    {
        "config": {
            "transfers": false
        }
    },
    {
        "config": {
            "meals": false
        }
    },
    {
        "config": {
            "all_inclusive": false
        }
    }
]

const obj = { 
  config: {} 
}

data.forEach((row) => {
  obj.config[Object.keys(row.config)[0]] = row.config[Object.keys(row.config)[0]];
})

console.log(obj);

1 Comment

Why use an external codepen when you can use a Stack Snippet here?
0

That should be a one-liner:

let data = [ 
    {
        "config": {
            "holes": 18
        }
    },
    {
        "config": {
            "single_cart": false
        }
    },
    /* more of your data.... */ 
]

const result = data.reduce((prev, {config}) => ({config: {...prev.config, ...config}}), {config: {}})

You can use reduce to flatten arrays or to create objects. You don't even need to declare a separate variable to assign your data to.

If you have a default config or previous data, you want to override, you can change the second parameter of the reduce function:


const defaultConfig = {
    config: {
      "holes": 0,
      "single_cart": true,
    }
}

const newConfig = data.reduce((prev, {config}) => ({config: {...prev.config, ...config}}), defaultConfig)

See more in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

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.