Як перетворити Об'єкт {} в масив [] пар ключових значень у JavaScript


243

Я хочу перетворити такий об’єкт:

{"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?

Відповіді:


429

Можна використовувати 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);


6
@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), що повертало б лише значення.


6
Шановні розробники, будь ласка, перевірте таблицю сумісності ECMA, перш ніж приймати ці приємні функції, сумісні лише з браузерами, випущеними хвилин тому.
andreszs

8
@andreszs Дивіться, чи можу я використовувати таблицю, якщо ви не проти відмовитись від підтримки IE (і в 2019 році, я сподіваюся, на ваш розум, що ви насправді цього не робите), тоді вам дуже зручно йти. FF 47 - з червня 2016 року, а Chrome 54 - з жовтня того ж року, край 14 серпня. Не зовсім хвилини тому.
Kyll

FYI: Object.entries поверне [ключ, значення], але ключ буде рядком, значення буде відрізнятися.
SHAHBAZ

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] ]

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

Тепер, незважаючи на те, що в нашому методі in-place все ще використовується два масиви, що містять пари ключів-значень (вхідні та вихідні масиви), загальна кількість масивів змінюється лише на одиницю. Вхідні та вихідні масиви насправді не заповнюються масивами, а скоріше посилання на масиви та ці посилання займають незначну кількість місця в пам'яті.

  • Змінення кожної пари ключових значень на місці призводить до незначного збільшення обсягу пам’яті, але потрібно ввести ще кілька символів.
  • Створення нового масиву для кожної пари ключ-значення призводить до подвоєння необхідної кількості пам’яті, але потрібно набрати кілька менших символів.

Ви можете піти ще на крок і повністю усунути зростання, змінивши масив записів на місці замість того, щоб відобразити його на новий масив:

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

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);


1
Це працювало для мене. У мене виникла проблема, коли імпорт JSON додав індекси, які унеможливлювали використання Angulars ngFor циклу. Це видалило індекси, зберігаючи структуру.
RAC

@RAC +1 для використання "індексів" замість "індексів". Сталі, архаїчні (тобто свавільні та безглуздо відхилення) англійські традиції!
Венрікс

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)виклику.
Венрікс

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, крім відповіді, наданої вище, ви також можете мати ключ у вихідному масиві.

Без об’єктних клавіш у вихідному масиві

для:

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([]), можливо, вам знадобиться це поліфункція, якщо ви ще цього не зробили:

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] = '...';

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));

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

Ми можемо змінити тип номер на рядок для ключа, як нижче:

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

Це моя проста безпрограшна реалізація:

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)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.