简体   繁体   中英

Map object values to keys - Javascript

I have an array from an API call.

var response = {
  "data": {
    "data": [{
      "1": "Arun",
      "index": "name"
    }, {
      "1": 70.78,
      "index": "score"
    }]
  }
}

I connect to a lot of other API's and they return me a similar response but the keys change. Sometimes it might be

var response = {
  "data": {
    "data": [{
      "values": "Harry",
      "index": "name"
    }, {
      "values": 45,
      "index": "score"
    }]
  }
}

var response = {
  "data": {
    "data": [{
      "4": "Richard",
      "index": "name"
    }, {
      "4": 98,
      "index": "score"
    }]
  }
}

I would like to get an array like this.

[
  {
    name: 'Arun',
    score: 70.78
  }
]

This is what I did.

 var response = { "data": { "data": [{ "1": "Arun", "index": "name" }, { "1": 70.78, "index": "score" }] } } const result = []; const mappedData = _.map(response.data.data, (item) => { return { [item.index]: item[1] }; }); const resultObject = _.reduce(mappedData, (result, currentObject) => { for (const key in currentObject) { if (currentObject.hasOwnProperty(key)) { result[key] = currentObject[key]; } } return result; }, {}); result.push(resultObject) console.log(result) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> 

So instead of hardcoding "1" or "values" in the map function, is there a more universal way to get the key and achieve the same result?

Thanks.

Use reduce rather than map , so you're updating the same object, not creating an array.

And since the property containing the value can vary, I use a loop to look for the first property that isn't named index , and use its value.

 var response = { "data": { "data": [{ "1": "Arun", "index": "name" }, { "1": 70.78, "index": "score" }] } } const mappedData = response.data.data.reduce((acc, item) => { var value; // find the property that isn't named "item" for (var i in item) { if (i != "index") { value = item[i]; break; } } acc[item.index] = value; return acc; }, {}); console.log(mappedData) 

There's no need for lodash for this, the built-in reduce function is fine (but _.reduce will work similarly).

Since you only care about the values of that object and it only has two keys you can do this quite easily in lodash with reduce & fromPairs :

 var response = { "data": { "data": [{ "1": "Arun", "index": "name" }, { "1": 70.78, "index": "score" }] } } const rv = (o) => _.reverse(_.values(o)) const r = _.reduce(response.data.data, (a,c) => _.fromPairs([rv(a), rv(c)])) console.log(r) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script> 

The same thing converted to ES6 would be:

 var response = { "data": { "data": [{ "1": "Arun", "index": "name" }, { "1": 70.78, "index": "score" }] } } const rv = (o) => Object.values(o).reverse() // reverse values const fp = (arr) => arr.reduce((r, [k,v]) => (r[k] = v, r), {}) // from pairs const result = response.data.data.reduce((a,c) => fp([rv(a), rv(c)])) console.log(result) 

The main idea here is to first get the object values in an array form, reverse them so the key & value are in the correct order and then reduce that array via from pairs to create the final object.

The main advantage of this approach is that we never deal with the object keys and only focus on the values which is what you really care about. This way the keys can be any value and it would still not matter.

You could try deleting the key-pair index and using the first value of the resulting object:

const mappedData = _.map(response.data.data, (item) => {
  var tempObj = Object.assign({}, item)
  var index = tempObj.index;
  delete tempObj.index;
  var otherData = Object.values(tempObj)[0];
  return {
    [index]: otherData
  };
});

Just modified the @barmar approach. I have used Object.keys to get keys from object. This will remove the any hard-coded dependency.

 var response = { "data": { "data": [{ "1": "Arun", "index": "name" }, { "1": 70.78, "index": "score" }] } } const mappedData = response.data.data.reduce((acc, item,i) => { var key = Object.keys(item); acc[item[key[1]]] = item[key[0]] return acc ; }, {}); console.log(mappedData) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM