6

This question might be similar to frequently asked one, but this one has some different approach.

In my angular 7 application, I have the following 5 arrays which needs to be converted to the below single object with dynamic key based on the id.

{
  "enabled-41": true,
  "enabled-42": true,
  "enabled-43": true,
  "enabled-44": true,
  "enabled-45": false,
  "abc-41": "some description 1",
  "abc-42": "some description 12",
  "abc-43": "some description 123",
  "abc-44": "some description 1234",
  "abc-45": null,
  "def-41": "some description 2",
  "def-42": "some description 23",
  "def-43": "some description 234",
  "def-44": "some description 2345",
  "def-45": null,
  "type-41": "def",
  "type-42": "abc",
  "type-43": "def",
  "type-44": "abc",
  "type-45": null,
  "weight-41": "25",
  "weight-42": "25",
  "weight-43": "25",
  "weight-44": "25",
  "weight-45": null
}

let arr = [
  {
    "id": 41,
    "abc": "some description 1",
    "def": "some description 2",
    "type": "def",
    "Criteria": {
      "id": 5,
      "question": "follow-up",
      "definition": "definition content",
      "status": true
    },
    "weight": 25,
    "enabled": true
  },
  {
    "id": 42,
    "abc": "some description 12",
    "def": "some description 23",
    "type": "abc",
    "Criteria": {
      "id": 1,
      "question": "coverage",
      "definition": "definition content",
      "status": true
    },
    "weight": 25,
    "enabled": true
  },
  {
    "id": 43,
    "abc": "some description 123",
    "def": "some description 234",
    "type": "def",
    "Criteria": {
      "id": 4,
      "question": "Price",
      "definition": "definition content",
      "status": true
    },
    "weight": 25,
    "enabled": true
  },
  {
    "id": 44,
    "abc": "some description 1234",
    "def": "some description 2345",
    "type": "abc",
    "Criteria": {
      "id": 3,
      "question": "Exchange",
      "definition": "definition content",
      "status": true
    },
    "weight": 25,
    "enabled": true
  },
  {
    "id": 45,
    "Criteria": {
      "id": 2,
      "definition": "definition conent",
      "question": "Random",
      "status": true
    },
    "type": null,
    "abc": null,
    "def": null,
    "weight": 0,
    "enabled": false
  }
];

let result = arr.reduce(function(obj, item) {
    obj[item] = item.value;
    return obj;
}, {})

console.log(result);

I have tried using reduce function, but cannot able to get the right way to convert to a single object with the above format based on dynamic key (joining id with hypen).

Can someone help me with this?

Jack Bashford
  • 38,499
  • 10
  • 36
  • 67
UI_Dev
  • 2,885
  • 12
  • 36
  • 79

5 Answers5

6

You can use reduce with Object.keys, and place all keys you wish to exclude in an array and check against that:

let arr = [{"id":41,"abc":"some description 1","def":"some description 2","type":"def","Criteria":{"id":5,"question":"follow-up","definition":"definition content","status":true},"weight":25,"enabled":true},{"id":42,"abc":"some description 12","def":"some description 23","type":"abc","Criteria":{"id":1,"question":"coverage","definition":"definition content","status":true},"weight":25,"enabled":true},{"id":43,"abc":"some description 123","def":"some description 234","type":"def","Criteria":{"id":4,"question":"Price","definition":"definition content","status":true},"weight":25,"enabled":true},{"id":44,"abc":"some description 1234","def":"some description 2345","type":"abc","Criteria":{"id":3,"question":"Exchange","definition":"definition content","status":true},"weight":25,"enabled":true},{"id":45,"Criteria":{"id":2,"definition":"definition conent","question":"Random","status":true},"type":null,"abc":null,"def":null,"weight":0,"enabled":false}];

let exclude = ["id", "Criteria"];

let result = arr.reduce((acc, curr) => {
  let id = curr.id;
  Object.entries(curr).forEach(([k, v]) => {
    if (!exclude.includes(k)) acc[`${k}-${id}`] = v;
  });
  return acc;
}, {});

console.log(result);
Jack Bashford
  • 38,499
  • 10
  • 36
  • 67
4

You code is almost there. But object keys order is not guaranteed. Inside the reduce callback function add the keys in the accumulator and corresponding value.

Use template literals & square notation while creating the object keys

let arr = [{
    "id": 41,
    "abc": "some description 1",
    "def": "some description 2",
    "type": "def",
    "Criteria": {
      "id": 5,
      "question": "follow-up",
      "definition": "definition content",
      "status": true
    },
    "weight": 25,
    "enabled": true
  },
  {
    "id": 42,
    "abc": "some description 12",
    "def": "some description 23",
    "type": "abc",
    "Criteria": {
      "id": 1,
      "question": "coverage",
      "definition": "definition content",
      "status": true
    },
    "weight": 25,
    "enabled": true
  },
  {
    "id": 43,
    "abc": "some description 123",
    "def": "some description 234",
    "type": "def",
    "Criteria": {
      "id": 4,
      "question": "Price",
      "definition": "definition content",
      "status": true
    },
    "weight": 25,
    "enabled": true
  },
  {
    "id": 44,
    "abc": "some description 1234",
    "def": "some description 2345",
    "type": "abc",
    "Criteria": {
      "id": 3,
      "question": "Exchange",
      "definition": "definition content",
      "status": true
    },
    "weight": 25,
    "enabled": true
  },
  {
    "id": 45,
    "Criteria": {
      "id": 2,
      "definition": "definition conent",
      "question": "Random",
      "status": true
    },
    "type": null,
    "abc": null,
    "def": null,
    "weight": 0,
    "enabled": false
  }
];

let result = arr.reduce(function(obj, item) {
  obj[`enabled-${item.id}`] = item.enabled;
  obj[`abc-${item.id}`] = item.abc;
  obj[`def-${item.id}`] = item.def;
  obj[`type-${item.id}`] = item.type;
  obj[`weight-${item.id}`] = item.weight;
  return obj;
}, {});
console.log(result)
brk
  • 43,022
  • 4
  • 37
  • 61
2

Assuming you want to exclude all the properties whose value is an object maybe you can go with this generic idea that uses Object.entries() to traverse the inner objects and some destructuring features.

let arr=[{"id":41,"abc":"some description 1","def":"some description 2","type":"def","Criteria":{"id":5,"question":"follow-up","definition":"definition content","status":true},"weight":25,"enabled":true},{"id":42,"abc":"some description 12","def":"some description 23","type":"abc","Criteria":{"id":1,"question":"coverage","definition":"definition content","status":true},"weight":25,"enabled":true},{"id":43,"abc":"some description 123","def":"some description 234","type":"def","Criteria":{"id":4,"question":"Price","definition":"definition content","status":true},"weight":25,"enabled":true},{"id":44,"abc":"some description 1234","def":"some description 2345","type":"abc","Criteria":{"id":3,"question":"Exchange","definition":"definition content","status":true},"weight":25,"enabled":true},{"id":45,"Criteria":{"id":2,"definition":"definition conent","question":"Random","status":true},"type":null,"abc":null,"def":null,"weight":0,"enabled":false}];

let result = arr.reduce((obj, {id, ...rest}) =>
{
    Object.entries(rest).forEach(([k, v]) =>
    {
        if (Object(v) !== v) obj[`${k}-${id}`] = v;
    });

    return obj;
}, {});

console.log(result);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Shidersz
  • 15,614
  • 2
  • 15
  • 40
1

Oh, man... I just got beat. Here's my solution.

let arr= [] // hold the final object array
let keys = [] // temp item to hold the value of each key

    // iterate over each key
    Object.keys(input).forEach((key) => {  
    let pair = key.split('-') // split the key into the real key and the index

    // if the index isn't in the array, push it there (this keeps the same order)
    if (keys.indexOf(pair[1])===-1) { 
        keys.push(pair[1])
    }

    // use object.assign to add the keys to the existing object in the right place in the array. 
    arr[keys.indexOf(pair[1])] = Object.assign({}, arr[keys.indexOf(pair[1])], {[pair[0]]: input[key]}, { id: pair[1] }) 

})
tagyoureit
  • 1,087
  • 1
  • 7
  • 14
0

function getFilteredData(arr) {
  const result = {};
  arr.forEach(item => {
    const { id, Criteria, ...rest } = item;
    Object.entries(rest).map(([key, value]) => {
      result[`${key}-${id}`] = value;
    });
  });
  return result;
}

let arr = [
  {
    id: 41,
    abc: 'some description 1',
    def: 'some description 2',
    type: 'def',
    Criteria: {
      id: 5,
      question: 'follow-up',
      definition: 'definition content',
      status: true
    },
    weight: 25,
    enabled: true
  },
  {
    id: 42,
    abc: 'some description 12',
    def: 'some description 23',
    type: 'abc',
    Criteria: {
      id: 1,
      question: 'coverage',
      definition: 'definition content',
      status: true
    },
    weight: 25,
    enabled: true
  },
  {
    id: 43,
    abc: 'some description 123',
    def: 'some description 234',
    type: 'def',
    Criteria: {
      id: 4,
      question: 'Price',
      definition: 'definition content',
      status: true
    },
    weight: 25,
    enabled: true
  },
  {
    id: 44,
    abc: 'some description 1234',
    def: 'some description 2345',
    type: 'abc',
    Criteria: {
      id: 3,
      question: 'Exchange',
      definition: 'definition content',
      status: true
    },
    weight: 25,
    enabled: true
  },
  {
    id: 45,
    Criteria: {
      id: 2,
      definition: 'definition conent',
      question: 'Random',
      status: true
    },
    type: null,
    abc: null,
    def: null,
    weight: 0,
    enabled: false
  }
];

console.log(getFilteredData(arr));
Mohammed Ashfaq
  • 2,808
  • 2
  • 11
  • 18