2012-08-10 30 views
2

我想知道如何在更清洁和最佳的方式做到这一点:的Javascript,重复的对象键N倍,为N其值

我有具有以下结构的对象:

{ 
    "125": 2, 
    "439": 3, 
    "560": 1, 
    "999": 2, 
    ... 
} 

我想创建一个重复每个键的平面数组,它的值表示的次数。和转换键(字符串)为整数的奖励点。在这个例子中,结果数组应该是:

[ 125, 125, 439, 439, 439, 560, 999, 999 ] 

我试过了几种方法,但他们都看起来过度设计。肯定有一个更简单的方法。 这是我和下划线了(并返回一个字符串数组,也不是整数):

_.compact(_.flatten(_.map(files, function(num, id) { 
    return new Array(num+1).join('$'+id).split('$') 
}))) 

我知道有很多方法可以做到这一点。我只想要一个干净而快捷的方式。作为一个红宝石开发商也可能是一样简单:提前

> files = {"125" => 2, "439" => 3, "560" => 1, "999" => 2} 
=> {"125"=>2, "439"=>3, "560"=>1, "999"=>2} 
> files.map {|key, value| [key.to_i] * value}.flatten 
=> [125, 125, 439, 439, 439, 560, 999, 999] 

感谢。

回答

1

试试这个:

var obj = { 
    "125": 2, 
    "439": 3, 
    "560": 1, 
    "999": 2 
} 

var arr = []; 

for (prop in obj) { 
    for (var i = 0; i < obj[prop]; i++) 
     arr.push(parseInt(prop)); 
} 
1

我知道这是普通的JavaScript,但比你发布的代码似乎更清洁对我说:

var dict = { 
    "125": 2, 
    "439": 3, 
    "560": 1, 
    "999": 2 
} 
var result = []; 

for(key in dict) 
    for(i = 0; i < dict[key]; i++) 
     result.push(key * 1); 

alert(result); 
0

嗯......不知道如果我在拿到,但也许是这样的:

var myObj = { 
    "125": 2, 
    "439": 3, 
    "560": 1, 
    "999": 2 
}, 
myArray = []; 

for(k in myObj){ 
    for(i = 0; i < myObj[k]; i++){ 
     myArray.push(k); 
    } 
} 
console.log(myArray) 
+0

正确的,只是他想的整数,所以你应该添加值,之前使用'parseInt函数()'或类似的东西阵列。 – jeff 2012-08-10 17:44:04

0

这些方法是否更清洁是相当主观的:

// some helper function for creating an array with repeated values 
function repeat(val, times) { 
    var arr = []; 
    for(var i = 0; i < times; i = arr.push(val)); 
    return arr; 
} 

function convert(obj) { 
    var result = [], key; 
    for(key in obj) { 
     result = result.concat(repeat(+key, obj[key])); 
    } 
    return result; 
} 

还是更注重功能的做法:

Object.keys(obj).reduce(function(result, key) { 
    return result.concat(repeat(+key, obj[key])); 
}, []); 

// with underscore.js 
_.reduce(_.keys(obj), function(result, key) { 
    return result.concat(repeat(+key, obj[key])); 
}, []); 
+1

'push'返回新的长度,所以我认为你需要在每次迭代中将'obj [k]'添加到'l'。 – zzzzBov 2012-08-10 17:30:04

+0

@zzzzBov:对,谢谢。 – 2012-08-10 17:31:28

+0

你的例子都不行。此外,通过轻松地错过+操作将字符串转换为整数有点困难,并且使用奇怪的while循环并没有什么帮助。 – zatatatata 2012-08-10 17:31:46

0

与其他答案的问题上面的是,在JavaScript中的for..in语言结构将涉及从对象的原型链上的所有按键。在这种情况下,我们应该检查并添加正确的密钥。

var obj= { 
    "125": 2, 
    "439": 3, 
    "560": 1, 
    "999": 2 
} 

var arr=[]; 

for (var item in map) { 
    //important check! 
    if (map.hasOwnProperty(item)) { 
    arr.push(item); 
    } 
} 

另见:http://www.yuiblog.com/blog/2006/09/26/for-in-intrigue/

+0

你有一个观点,但只有在扩展了Object的原型时才会发生。这样做通常令人fr目,而一些知名的库不支持在这种情况下运行。这是可以理解的,因为支持它意味着每次迭代一个对象时都会应用您的答案(并且每次迭代花费对hasOwnProperty()的调用)。 – 2012-08-10 17:43:40

+0

以及我假设他的flattening代码收到一个对象作为参数,所有的意图和目的可能来自原型对象。至于衡量“成本”来调用hasOwnProperty与该函数的行为是否正确,我认为可以安全地说出哪一个是更安全的选择。我不喜欢这样做检查自己,但这是JavaScript构造如何工作。 – Hyangelo 2012-08-10 17:48:05

0

一个辅助函数:

function flatten(obj){ 
//static Array method: create array (a elements, value b) 
Array.aXb = Array.aXb || function(a,b){ 
    b = b || 0; 
    return String(this(a)).split(',').map(function(){return b;}); 
} 
//obj2array 
var arr = []; 
for (var k in obj) 
    if (+obj[k]) arr = arr.concat(Array.aXb(+obj[k],k)); 
return arr; 
} 
var obj= {"125": 2,"439": 3, 
      "560": 1,"999": 2 }, 
flatten(obj); //=> [125,125,439,439,439,560,999,999]