从jQuery数组中选择随机

时间:2013-05-07 20:31:22

标签: jquery arrays

我有一个JSON对象数组,我想从中获取几个随机值。 我自己写了一些代码,最后它起作用了,但是甚至显示它都很难看。

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

我们有一个像这样的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"
      }
    }
]

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

  • "type" = "Gebied"
  • 的2项功能
  • "Type" = "Land"
  • 的1个功能

实际上,要选择的功能数量(在此示例中为1和2)可能不同(单个类型最多20个)。

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

我很好奇你们会采取哪些方法,希望有助于创建一个真正好的代码块,而不是我现在使用的近100条代码规则(甚至没有完成)。

3 个答案:

答案 0 :(得分: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)];

<强>更新

要输入给定数字,确定要选择的随机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());

答案 1 :(得分:0)

我不会从头开始编码,而是使用其中一个丰富的库,例如underscore

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

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

这只是一点,但如果这是你的意思,那么剩下的就是直截了当。

答案 2 :(得分: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页面底部有一个垫片)。