Сопоставить значения объекта с ключами - Javascript - PullRequest
0 голосов
/ 30 октября 2018

У меня есть массив из вызова API.

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

Я подключаюсь ко многим другим API, и они возвращают мне аналогичный ответ, но ключи меняются. Иногда это может быть

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

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

Я бы хотел получить такой массив.

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

Это то, что я сделал.

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>

Таким образом, вместо жесткого кодирования "1" или "значений" в функции карты, существует ли более универсальный способ получения ключа и достижения того же результата?

Спасибо.

Ответы [ 4 ]

0 голосов
/ 02 ноября 2018

Поскольку вам важны только значения этого объекта и , он имеет только два ключа, вы можете сделать это довольно легко в lodash с помощью уменьшите & 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>

То же самое, преобразованное в ES6 будет:

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)

Основная идея здесь состоит в том, чтобы сначала получить значения объектов в виде массива, перевернуть их так, чтобы key & value были в правильном порядке, а затем reduce этот массив через from pairs, чтобы создать окончательный вариант. объект.

Основным преимуществом этого подхода является то, что мы никогда не имеем дело с ключами объекта и фокусируемся только на значениях, которые вам действительно интересны. Таким образом, ключи могут иметь любое значение, и это все равно не имеет значения.

0 голосов
/ 30 октября 2018

Вы можете попробовать удалить пару ключей index и использовать первый value полученного объекта:

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
  };
});
0 голосов
/ 30 октября 2018

Только что изменил подход @barmar. Я использовал Object.keys, чтобы получить ключи от объекта. Это удалит любую жестко запрограммированную зависимость.

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>
0 голосов
/ 30 октября 2018

Используйте reduce вместо map, поэтому вы обновляете тот же объект, а не создаете массив.

И так как свойство, содержащее значение, может изменяться, я использую цикл для поиска первого свойства, которое не называется index, и использую его значение.

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)

Для этого нет необходимости в lodash, встроенная функция reduce в порядке (но _.reduce будет работать аналогично).

...