2013-05-07 104 views
3

我有一个JSON对象数组,我想从中获取一对随机值。 我自己写了一些代码,最后它运行正常,但它甚至难以显示。从jQuery数组中随机选择

所以这就是我开始这个问题的原因。什么应该是好的/好的方法来编码以下情况?

我们已经有了一个JSON数组是这样的:(这是再实际,但只是一对夫妇为例)

"features" : [ 
    { 
     "attributes" : { 
     "OBJECTID" : 6, 
     "Type" : "Gebied" 
     } 
    }, 
    { 
     "attributes" : { 
     "OBJECTID" : 70, 
     "Type" : "Water" 
     } 
    }, 
    { 
     "attributes" : { 
     "OBJECTID" : 80, 
     "Type" : "Water" 
     } 
    }, 
    { 
     "attributes" : { 
     "OBJECTID" : 91, 
     "Type" : "Land" 
     } 
    }, 
    { 
     "attributes" : { 
     "OBJECTID" : 66, 
     "Type" : "Gebied" 
     } 
    }, 
    { 
     "attributes" : { 
     "OBJECTID" : 78, 
     "Type" : "Land" 
     } 
    } 
] 

从该数组我们要创建一个新的简单的数组,其中包含,例如:

  • 2特征与"type" = "Gebied"
  • 1特征与"Type" = "Land"

实际上,要选择的要素数(在本示例中为1和2)可以不同(对于单个类型最多可以有20个)。

而最重要的是,这些功能应该随机选择。

我很好奇,接近你们会采取并希望它有助于创建一个真正的代码块来做到这一点,而不是我现在使用的几乎100个代码规则(甚至没有完成)。

回答

1

不知道这是你想要的,如果没有,我就删除它..但这里有云:

var gebied = 0; 
var id = new Array(); 

for(var i = 0; i < features.length; i++) 
{ 
    if(features[i].attributes.Type == 'Gebied') 
    { 
    // saves the gebied instance +1 
    id[gebied] = features[i].attributes.OBJECTID; 
    gebied++; 
    } 
} 

// pick random 2 from gebied array 
var id1; 
var id2; 
var idListLength = id.length; 

id1 = id[Math.floor(Math.random() * idListLength)]; 

if (idListLength > 1) { 
    do { 
     id2 = id[Math.floor(Math.random() * idListLength)]; 
    } while(id1 == id2); 
} 

// if it's just one random pick from array 
var id1 = id[Math.floor(Math.random() * id.length)]; 

UPDATE

,此外,输入给定数量的确定随机ID的数目来接:

function getRandomArrayElements(arr, count) { 
    var randoms = [], clone = arr.slice(0); 
    for (var i = 0, index; i < count; ++i) { 
     index = Math.floor(Math.random() * clone.length); 
     randoms.push(clone[index]); 
     clone[index] = clone.pop(); 
    } 
    return randoms; 
} 

function pickRandom(count) 
{ 
    var gebied = 0; 
    var id = new Array(); 

    for(var i = 0; i < features.length; i++) 
    { 
    if(features[i].attributes.Type == 'Gebied') 
    { 
     // saves the gebied instance +1 
     id[gebied] = features[i].attributes.OBJECTID; 
     gebied++; 
    } 
    } 

    return getRandomArrayElements(id, count); 
} 

实施例:

pickRandom($('#random').val()); 
+0

哎呀,我喜欢你的方法很多!谢谢。还有一件事:实际上,要选择的项目数量也是可变的。所以(基于输入框)有时我想选择3个“gebied”实例,而另一个时候我想选择其中的15个。我也加入了这个问题。所以我认为最后一部分需要进行一些修改。有什么想法吗? – 2013-05-07 21:47:52

+0

我做了一个小小的研究,这里是你的情况的一个更新代码http://fiddle.jshell.net/XsYgy/1/ ...如果它是正确的,我会添加到主要答案。 – Fabi 2013-05-07 21:48:54

+0

在jsFiddle中,它绝对看起来像我试图实现的。所以,如果你将它添加到你的答案,这将是很好的。我明天再测试一下,然后回复你,很可能通过接受你的答案。为此我非常感谢! – 2013-05-07 21:52:17

0

我不会从头开始编写代码,但利用现有丰富的图书馆之一,像underscore

var gebied = _.filter(features, function(f) { 
    return f.attributes.type === 'Gebied'; 
}); 

var result = []; 
result.push(gebied[_.random(0, gebied,length)]) 

这只是一个位,但如果这是你的意思,然后剩下的就是简单。

0

下面是更多关于该问题的功能性方法,它具有坚持DRY原则并产生相当可读和可重用代码的优点。基本上,一对滤波器完成所有的工作:

function isType(t) { // filter by Type 
    return function (el) { 
    return el.attributes.Type === t; 
    } 
} 

function chooseR(r) { // filter for choosing r of length 
    var found = 0; 

    return function (el, idx, arr) { 
    // calculate probability to keep [# needed/# left] 
    var keep = Math.random() < (r - found)/(arr.length - idx); 

    // increment if keeping 
    keep && found++; 

    return keep; 
    } 
} 

var myGebied = features.filter(isType('Gebied')).filter(chooseR(2)), 
    myLand = features.filter(isType('Land')).filter(chooseR(1)); 

chooseR算法只是一个在the answer to Select a random N elements from List的过滤器适配。显然,chooseR(1)是愚蠢的,但我只是保持它显示的方法的原则。

如果你不关心IE8,Array.prototype.filter是标准的ES5规格(see browser support)。否则,请确保在某处找到垫片(链接到底部的MDN页面)。