2016-05-27 6 views
1

У меня есть объект, в котором значения являются целыми числами. Что-то вроде: {cat: 2, dog: 1, bird: 4}Создание массива на основе объекта

Я хочу создать массив, в котором ключ в объекте включен в массив столько же раз, сколько и значение. Итак, в этом случае: [«кошка», «кошка», «собака», «птица», «птица», «птица», птица »)

Ключи всегда будут одинаковыми, но значение может быть 0.

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

+0

Я не могу думать лучшего способа сделать это, чем это. Это не обычная операция, поэтому в ней ничего нет. – Barmar

+0

Если вы используете библиотеку, такую ​​как underscore.js, она может предоставить функцию для нажимания строки N раз, где N - это значение от объекта. – Barmar

+0

Вы можете перебирать клавиши с помощью цикла 'for in'. Не нужно повторять код для каждого из ваших ключей. – Bergi

ответ

2

Demo:..? https://jsfiddle.net/81LxL1qt/1/

var obj = {cat: 2, dog: 1, bird: 4}; 
 

 
var results = []; 
 

 
for (var key in obj) 
 
    for (var i = 0, count = obj[key]; i < count; i++) 
 
    results.push(key); 
 

 
console.log(results);

+0

Вам не нужно, чтобы 'obj.hasOwnProperty (key)' check – Bergi

+0

Вы правы, обновлено –

+0

Спасибо! Это то же самое, что я думал, но гораздо более кратким, чем я мог придумать. –

2

Очень функциональный метод сделать это будет:

var obj = {cat: 2, dog: 1, bird: 4}; 
 
var arr = [].concat(...Object.keys(obj).map(key => Array(obj[key]).fill(key))); 
 
console.log(arr);

В основном то, что он делает это, он gets the keys объекта, а затем maps каждый ключ к массиву filled с этим ключом. Затем это flattens результирующий 2D-массив в 1D-массив с использованием .concat().

Дополнительное чтение: Arrow functions (=>) Spread operator (...)

+0

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

+0

@CristiPufu Это не хвастается, это учение :) Если мне повезет, они будут искать то, что каждая часть а затем они больше не станут новичком :) Это сообщение, конечно, научило меня и некоторым трюкам. (Особенно Oriol, это было потрясающе) – 4castle

1

Используя выражение немедленно выполняется генератор,

var obj = {cat: 2, dog: 1, bird: 4}; 
 
var output = [...function*() { 
 
    for(var key of Object.keys(obj)) 
 
    for(var i=0; i<obj[key]; ++i) 
 
     yield key; 
 
}()]; 
 
console.log(output);

+0

Почему бы не 'for (var key in obj)'? – 4castle

+0

@ 4castle Используйте 'for..in', если вы хотите также иследовать свойства. – Oriol

+0

Gotcha, хотя я сомневаюсь, что есть унаследованные свойства. Вопрос предложил довольно простой объект. – 4castle

0

Это, как я хотел бы сделать это;

var arr = ["cat", "cat", "dog", "bird", "bird", "bird", "bird"], 
 
    obj = arr.reduce((p,c) => (p[c] = p[c] ? ++p[c] : 1 ,p) ,{}); 
 
console.log(obj);

Так хорошо пятницу ночью .Это и я долго не будет, пока я получить правильный ... (футы. Sia)

var obj = {cat: 2, dog: 1, bird: 4}, 
 
    arr = Object.keys(obj).reduce((p,c) => p.concat((new Array(obj[c])).fill(c)) ,[]); 
 
console.log(arr);

Простите еще раз ... Думаю, теперь все в порядке.

+2

Отличное решение! Но вы решили обратную операцию :(Они хотели, чтобы ваш выход был входом. – 4castle

+0

Ничего себе .. да, я думаю, у меня было немного до пива до ночи ... – Redu

0

Метание в быстром решении lodash, если это вариант для вас:

function mapObjectToArray(obj) { 
    var arr = []; 
    _.forIn(obj, function(value, key) { 
    _.times(value, function() { 
     arr.push(key); 
    }); 
    }); 
    return arr; 
} 

var petCt = {'cat': 2, 'dog': 1, 'bird': 3, 'ocelot': 0, 'sugar glider': 1}; 

<!DOCTYPE html> 
 
<html> 
 

 
    <head> 
 
    <script data-require="[email protected]" data-semver="4.6.1" src="https://cdn.jsdelivr.net/lodash/4.6.1/lodash.js"></script> 
 
    <link rel="stylesheet" href="style.css" /> 
 
    <script src="script.js"></script> 
 
    </head> 
 

 
    <body> 
 
    <pre id="resultArray"></pre> 
 

 

 
    <script> 
 
    var petCt = {'cat': 2, 'dog': 1, 'bird': 3, 'ocelot': 0, 'sugar glider': 1}; 
 
    
 
    function mapObjectToArray(obj) { 
 
     var arr = []; 
 
     _.forIn(obj, function(value, key) { 
 
     _.times(value, function() { 
 
      arr.push(key); 
 
     }); 
 
     }); 
 
     return arr; 
 
    } 
 
    
 
    var elem = document.getElementById('resultArray'); 
 
    elem.innerHTML = mapObjectToArray(petCt); 
 
    
 
    </script> 
 
    
 
    </body> 
 
</html>

1

С помощью функции Lodash forOwn

var result = []; 
_.forOwn({cat: 2, dog: 1, bird: 4}, function(value, key){ 
    result.push(...Array(value).fill(key)); 
}); 
+0

'_.times' берет функцию в качестве второго параметра. '_.times (значение, _.constant (key))' работает хотя :) – 4castle

+0

@ 4Castle вы абсолютно правы. Вместо этого вы можете использовать Array.fill(), поскольку третья функция lodash была немного избыточной. – JellyRaptor

Смежные вопросы