2013-05-07 108 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頁面)。