Как преобразовать Object {} в Array [] пар ключ-значение в JavaScript

244

Я хочу преобразовать объект следующим образом:

{"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}

в массив пар ключ-значение, как это:

[[1,5],[2,7],[3,0],[4,0]...].

Как я могу преобразовать Объект в Массив пар ключ-значение в JavaScript?

Соптареану алексей
источник

Ответы:

430

Вы можете использовать Object.keys()и map()сделать это

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
var result = Object.keys(obj).map(function(key) {
  return [Number(key), obj[key]];
});

console.log(result);

Ненад Вракар
источник
7
@blvckasvp Вы используете числа в качестве ключей? Если нет, то при попытке преобразовать ваш ключ в число он потерпит неудачу и NaNвместо этого вернется . Если вы хотите использовать строки как ключи, изменить возвращение из [Number(key), obj[key]]к [key, obj[key]]или использовать в Object.entriesкачестве @Pila предложило в их ответе
scottbot95
123

Лучший способ это сделать:

var obj ={"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10"‌​:0,"11":0,"12":0} 
Object.entries(obj);

Вызов entries, как показано здесь, вернет [key, value]пары, как просил аскер.

В качестве альтернативы вы можете вызвать Object.values(obj), который будет возвращать только значения.

Pila
источник
6
Уважаемые разработчики, пожалуйста, ознакомьтесь с таблицей совместимости ECMA, прежде чем переходить на эти приятные функции, которые совместимы только с браузерами, выпущенными несколько минут назад.
andreszs
8
@andreszs См. « Могу ли я использовать таблицу», если вы не против отказаться от поддержки IE (а в 2019 году я надеюсь на ваше здравомыслие, которого вы на самом деле не делаете), тогда вы довольно хороши. FF 47 с июня 2016 года, а Chrome 54 с октября того же года, Edge 14 августа. Не совсем несколько минут назад.
Kyll
К вашему сведению: Object.entries вернет [ключ, значение], но ключ будет строкой, значение будет отличаться.
Шахбаз
62

Object.entries()возвращает массив, элементы которого являются массивами, соответствующими перечисляемым [key, value]парам свойств, найденным непосредственно при object. Порядок свойств такой же, как и при циклическом переключении значений свойств объекта вручную.

- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Description

В Object.entriesфункции возвращает почти точные результаты вы просите, за исключением клавиша являются строками вместо цифр.

const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};

console.log(Object.entries(obj));

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

const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};

const toNumericPairs = input => {
    const entries = Object.entries(input);
    return entries.map(entry => Object.assign(entry, { 0: +entry[0] }));
}

console.log(toNumericPairs(obj));

Я использую функцию стрелки и Object.assignдля обратного вызова карты в приведенном выше примере, чтобы я мог сохранить ее в одной инструкции, используя тот факт, что Object.assignвозвращается объект, которому назначен объект, а возвращаемое значение функции стрелки одной инструкции является результатом инструкции.

Это эквивалентно:

entry => {
    entry[0] = +entry[0];
    return entry;
}

Как упомянуто @TravisClarke в комментариях, функцию карты можно сократить до:

entry => [ +entry[0], entry[1] ]

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

Теперь, хотя при использовании нашего метода на месте все еще используются два массива, которые содержат пары ключ-значение (входной и выходной массивы), общее количество массивов изменяется только на один. Массивы ввода и вывода на самом деле не заполнены массивами, а скорее ссылками на массивы, и эти ссылки занимают незначительное место в памяти.

  • Изменение каждой пары ключ-значение на месте приводит к незначительному увеличению объема памяти, но требует ввода еще нескольких символов.
  • Создание нового массива для каждой пары ключ-значение приводит к удвоению объема требуемой памяти, но требует ввода нескольких символов меньше.

Вы можете сделать еще один шаг и полностью исключить рост, изменив массив записей на месте, а не сопоставляя его с новым массивом:

const obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};

const toNumericPairs = input => {
  const entries = Object.entries(obj);
  entries.forEach(entry => entry[0] = +entry[0]);
  return entries;
}

console.log(toNumericPairs(obj));


источник
1
Мне нравится функциональный подход. Как короткая альтернатива:Object.entries(obj).map(e => [+e[0], e[1]]);
Трэвис Кларк
21

Напомним, некоторые из этих ответов теперь на 2018 году, где ES6 является стандартом.

Начиная с объекта:

let const={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
  • Просто вслепую получая значения в массиве, пофиг на ключи:

const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.values(obj));
//[9,8,7,6,5,4,3,2,1,0,5]

  • Простое получение пар в массиве:

const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.entries(obj));
//[["1",9],["2",8],["3",7],["4",6],["5",5],["6",4],["7",3],["8",2],["9",1],["10",0],["12",5]]

  • То же, что и предыдущий, но с цифровыми клавишами на каждой паре:

const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.entries(obj).map(([k,v])=>[+k,v]));
//[[1,9],[2,8],[3,7],[4,6],[5,5],[6,4],[7,3],[8,2],[9,1],[10,0],[12,5]]

  • Использование свойства объекта в качестве ключа для нового массива (может создавать разреженные массивы):

const obj={"1":9,"2":8,"3":7,"4":6,"5":5,"6":4,"7":3,"8":2,"9":1,"10":0,"12":5};
console.log(Object.entries(obj).reduce((ini,[k,v])=>(ini[k]=v,ini),[]));
//[undefined,9,8,7,6,5,4,3,2,1,0,undefined,5]

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

  • Карта вместо массива

Наконец (не часть исходного вопроса, но для полноты), если вам нужно легко искать, используя ключ или значение, но вы не хотите разреженных массивов, дубликатов и переупорядочения без необходимости преобразования в числовые ключи ( даже может получить доступ к очень сложным ключам), тогда массив (или объект) - это не то, что вам нужно. Я буду рекомендовать Mapвместо этого:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

let r=new Map(Object.entries(obj));
r.get("4"); //6
r.has(8); //true
CarlosH.
источник
2
Четвертый пункт и далее не имеет никакого отношения к вопросу, а остальная часть вашего ответа просто суммирует три верхних ответа здесь. Этот ответ не привносит в дискуссию ничего, что еще не было здесь или не является абсолютно неуместным.
Да, в качестве первой строки, это сводка ответов, затем обновите их, чтобы использовать современные методы ES6 вместо функций полного удара. Четвертый ответ полезен, когда вы перемещаете массивы JSON из языка, который поддерживает ассоциативные массивы (например, PHP).
КарлосХ.
Все методы, представленные здесь, уже представлены в их простой форме в двух из трех лучших ответов, они не в функциях, поэтому я не знаю, о чем вы там говорите. Что касается 4-го, как я уже сказал, это совершенно не имеет отношения к заданному вопросу. Это может относиться к другому вопросу, но не к этому. В любом случае, JSON - это JSON, независимо от того, создан он с использованием PHP, JavaScript или Haskell.
18

Еще одно решение, если у Object.entriesвас не получится.

const obj = {
      '1': 29,
      '2': 42
    };
const arr = Array.from(Object.keys(obj), k=>[`${k}`, obj[k]]);
console.log(arr);

bigh_29
источник
1
Это сработало для меня. Я столкнулся с проблемой, когда при импорте JSON добавлялись индексы, которые делали невозможным использование цикла Angulars ngFor. Это удалило индексы при сохранении структуры.
RAC
@RAC +1 за использование «индексов» вместо «индексов». Оставь архаичные (т. Е. Произвольные и бессмысленно девиантные) английские традиции!
Venryx
12

В Ecmascript 6,

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0};

var res = Object.entries(obj);

console.log(res);

играть на скрипке

Нагешвар Редди Пандем
источник
Не уверен, почему за это проголосовали, он работал отлично
sMyles
1
Я не понизил голос, но обратите внимание, что эта .map((value)=>(value))часть не имеет смысла - она ​​просто возвращает массив записей, точно эквивалентный массиву, полученному при Object.entries(obj)вызове.
Venryx
8

Использование Object.keysи Array#mapметоды.

var obj = {
  "1": 5,
  "2": 7,
  "3": 0,
  "4": 0,
  "5": 0,
  "6": 0,
  "7": 0,
  "8": 0,
  "9": 0,
  "10": 0,
  "11": 0,
  "12": 0
};
// get all object property names
var res = Object.keys(obj)
  // iterate over them and generate the array
  .map(function(k) {
    // generate the array element 
    return [+k, obj[k]];
  });

console.log(res);

Пранав С Балан
источник
7

Используйте Object.entriesдля получения каждого элемента объекта в key & valueформате, а затем mapчерез них, как это:

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}

var res = Object.entries(obj).map(([k, v]) => ([Number(k), v]));

console.log(res);

Но, если вы уверены, что ключи будут в прогрессивном порядке, вы можете использовать Object.valuesи Array#mapсделать что-то вроде этого:

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}; 

                        // idx is the index, you can use any logic to increment it (starts from 0)
let result = Object.values(obj).map((e, idx) => ([++idx, e]));

console.log(result);

Бороды
источник
5

Если вы используете lodash, это может быть так просто:

var arr = _.values(obj);
Адам Бустани
источник
5

С lodash, в дополнение к ответу, приведенному выше, вы также можете иметь ключ в массиве вывода.

Без ключей объекта в выходном массиве

для:

const array = _.values(obj);

Если obj следующее:

{ art”: { id: 1,  title: aaaa }, fiction”: { id: 22,  title: 7777”} }

Тогда массив будет:

[ { id: 1, title: aaaa }, { id: 22, title: 7777 } ]

С ключами объекта в выходном массиве

Если вы пишете вместо этого («жанр» - строка, которую вы выбираете):

const array= _.map(obj, (val, id) => {
    return { ...val, genre: key };
  });

Ты получишь:

[ 
  { id: 1, title: aaaa , genre: art”}, 
  { id: 22, title: 7777”, genre: fiction }
]
Йосси
источник
4

Я бы предложил это простейшее решение для использования Object.entries()

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
var result =Object.entries(obj)

console.log(result);

Стек Иронии
источник
1

Вы можете использовать Object.values([]), вам может понадобиться этот polyfill, если вы этого еще не сделали:

const objectToValuesPolyfill = (object) => {
  return Object.keys(object).map(key => object[key]);
};
Object.values = Object.values || objectToValuesPolyfill;

https://stackoverflow.com/a/54822153/846348

Тогда вы можете просто сделать:

var object = {1: 'hello', 2: 'world'};
var array = Object.values(object);

Просто помните, что массивы в js могут использовать только числовые ключи, поэтому, если вы использовали что-то еще в объекте, они станут `0,1,2 ... x``

Это может быть полезно для удаления дубликатов, например, если у вас есть уникальный ключ.

var obj = {};
object[uniqueKey] = '...';
Ozzie
источник
0

Использовать для в

var obj = { "10":5, "2":7, "3":0, "4":0, "5":0, "6":0, "7":0,
            "8":0, "9":0, "10":0, "11":0, "12":0 };

var objectToArray = function(obj) {
    var _arr = [];

    for (var key in obj) {
        _arr.push([key, obj[key]]);
    }
    return _arr;
}

console.log(objectToArray(obj));
wkyniston
источник
0

Рекурсивное преобразование объекта в массив

function is_object(mixed_var) {
    if (mixed_var instanceof Array) {
        return false;
    } else {
        return (mixed_var !== null) && (typeof( mixed_var ) == 'object');
    }
}


function objectToArray(obj) {
    var array = [], tempObject;
    for (var key in obj) {

        tempObject = obj[key];

        if (is_object(obj[key])) {
            tempObject = objectToArray(obj[key]);
        }
        array[key] = tempObject;
    }
    return array;
}
Марина Лебедева
источник
0

Мы можем изменить Number на String type для Key, как показано ниже:

var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0}
var result = Object.keys(obj).map(function(key) {
  return [String(key), obj[key]];
});
    
console.log(result);

Нагнат Мунгаде
источник
0

Это мое решение, у меня та же проблема, и кажется, что это решение работает для меня.

yourObj = [].concat(yourObj);
Куай-Гон Джинн
источник
0

Это моя простая реализация barebone:

let obj = {
  "1": 5,
  "2": 7,
  "3": 0,
  "4": 0,
  "5": 0,
  "6": 0,
  "7": 0,
  "8": 0,
  "9": 0,
  "10": 0,
  "11": 0,
  "12": 0
};    

const objectToArray = obj => {
      let sol = [];
      for (key in obj) {
        sol.push([key, obj[key]]);
      }
      return sol;
    };

objectToArray(obj)
Кетан Рамтеке
источник
0

Простое решение

`

var result = Object.keys(records).map(function (value) {
         return { [value]: records[value] };
});
console.log(result);

Folorunso
источник