【问题标题】:Using an array element only once仅使用一次数组元素
【发布时间】:2015-01-21 08:58:06
【问题描述】:

我是 JavaScript 新手,我想从我的数组中取出三个随机元素,它们需要不同。我已经设法得到三个不同的元素,然后我尝试通过 split 方法只取一个元素一次。但显然这并不起作用,可能有很多错误,因为这是我的第一个脚本之一。它有时也会说“未定义”。

http://jsfiddle.net/t4mtpm50/

HTML:

<span id="tot1"></span>, <span id="tot2"> und </span> und <span id="tot3"></span>

Javascript:

function getNumber() {
    random = Math.floor(Math.random() * students.length);
    students.splice(random,1);
    return random;
}

students = new Array("Paul", "Jan", "Fabian D.", "Fabian K.", "Lennard", 
                            "Robin", "Angelique", "Joyce", "Sarah", "Ajlin",
                            "Enes", "Leon", "Boran", "Joshua")    

getNumber();
tot1 = students[random];
getNumber();
tot2 = students[random];
getNumber();
tot3 = students[random];

document.getElementById('tot1').innerHTML = tot1;
document.getElementById('tot2').innerHTML = tot2;
document.getElementById('tot3').innerHTML = tot3;

【问题讨论】:

  • tot1 = students[random] 当该语句命中时,随机未定义。 random 是 getNumber 函数内的局部变量,但一旦该函数退出,该局部变量就不再可访问。应该是 tot1 = students[getNumber()];或 var RandomNumber = getNumber(); tot1 = 学生[随机数];
  • @frenchie 如果没有 var 或类似的关键字将 random 声明为本地,它将作为全局泄漏。 stackoverflow.com/questions/1470488
  • 通常你会像这样访问return 变量:var my_return_var = getNumber(); 就像@JonathanLonowski 提到的那样,你的变量表现得像全局变量,很容易在更大的代码中导致问题。
  • 如果我的解决方案不适合你,请告诉我。
  • 欢迎来到 StackOverflow!请参阅"Should questions include “tags” in their titles?",其中的共识是“不,他们不应该”。

标签: javascript jquery html arrays random


【解决方案1】:

通过使用.splice(),随机选择的名称实际上在被检索之前就被删除了,使得random 改为引用集合中的下一个名称:

var students = [ "Paul", "Jan", "Fabian D." ];
var random = 1;

console.log(students[random]); // "Jan"

students.splice(random, 1);

console.log(students);         // [ "Paul", "Fabian D." ]
console.log(students[random]); // "Fabian D."

random 试图引用最后一个元素时,会出现“它有时会说'未定义'”:

var students = [ "Paul", "Jan", "Fabian D." ];
var random = 2;

console.log(students[random]); // "Fabian D."

students.splice(random, 1);

console.log(students);         // [ "Paul", "Jan" ]
console.log(students[random]); // undefined, random is now out-of-bounds at 2

你可以使用.splice()的返回值,它是被移除元素的集合,重新定义getNumber()来代替返回一个元素而不是一个索引:

function getStudent() {
    var random = Math.floor(Math.random() * students.length);
    return students.splice(random, 1)[0]; // return the 1st and only removed element
}

var tot1 = getStudent(); // "Fabian D."
var tot2 = getStudent(); // "Enes"
var tot3 = getStudent(); // "Joyce"

http://jsfiddle.net/6gox6L1t/

【讨论】:

  • 你几乎同时得到了同样的想法:-)
  • 也谢谢你!似乎是一个更好的解决方案。
【解决方案2】:

我认为这将是一个更好、更简洁、更短的解决方案:

function getStudent(students) {
    var random = Math.floor(Math.random() * (students.length));
    var my_student = students.splice(random,1);
    return my_student;
}

var students = new Array("Paul", "Jan", "Fabian D.", "Fabian K.", "Lennard", 
                            "Robin", "Angelique", "Joyce", "Sarah", "Ajlin",
                         "Enes", "Leon", "Boran", "Joshua");


document.getElementById('tot1').innerHTML = getStudent(students);
document.getElementById('tot2').innerHTML = getStudent(students);
document.getElementById('tot3').innerHTML = getStudent(students);


您将当前的学生数组传递给 getStudent() 函数,这样您就可以避免在脚本中包含全局变量。 splice 返回删除的元素,因此您在此处获得了学生姓名并将其返回。

edit2:我对.length 上的-1 有误。 1Math.random() 的独家结果,所以你说得对。

http://jsfiddle.net/northkildonan/38rf42f7/1/

编辑:此方法完全避免在脚本中使用全局变量。

【讨论】:

  • 非常感谢!这似乎是最干净和最简单的方法
  • 使用Math.random() * (students.length - 1)意味着数组中的最后一项永远不能被选中。
  • @Phylogenesis 哦,是的,没错,谢谢! 1 在Math.random() 中是专有的,请阅读。所以这不是他“未定义”错误的原因。
  • 他出现undefined 错误的原因是因为他返回的索引代表他从数组中删除的元素。
  • @ProllyGeek 它不会。
【解决方案3】:

试试这个:

 students = new Array("Paul", "Jan", "Fabian D.", "Fabian K.", "Lennard",                   "Robin", "Angelique", "Joyce", "Sarah", "Ajlin",
"Enes", "Leon", "Boran", "Joshua")    


var arr = []
while(arr.length < 3){
  var randomnumber=Math.ceil(Math.random()*students.length-1)
  var found=false;
  for(var i=0;i<arr.length;i++){
    if(arr[i]==randomnumber){found=true;break}
  }
  if(!found)arr[arr.length]=randomnumber;
}
console.log(arr.valueOf());

tot1 = students[arr[0]];

tot2 = students[arr[1]];

tot3 = students[arr[2]];

document.getElementById('tot1').innerHTML = tot1;
document.getElementById('tot2').innerHTML = tot2;
document.getElementById('tot3').innerHTML = tot3;

请注意,长度应减 1,因为索引从 0 开始。

http://jsfiddle.net/t4mtpm50/6/

【讨论】:

  • 该代码甚至没有尝试多次阻止名称的出现。
  • @JukkaK.Korpela 好的,抱歉,我的答案已修正。
  • 非常感谢,这似乎有效。你能告诉我这到底是怎么工作的吗?我真的不明白:)
  • @SimonMathewson 算法非常简单,我创建了一个空数组并将长度设置为 3(计算您想要多少个不同的随机数),创建了一个生成随机数的循环,当一个number 生成它迭代数组以检查之前是否创建了相似的数字,如果是,它将生成新的数字,依此类推,直到找不到相似的数字,最后使用数组元素引用您的原始数组。如果我的回答是正确的,请将其标记为正确的。
【解决方案4】:

另一种选择是对整个学生列表进行洗牌,然后从洗牌的集合中挑选前三个。 (这里的shuffle函数改编自https://stackoverflow.com/a/6274398/567595。)

function shuffle(array) {
    var i, temp, j;
    for (i = array.length; i; i--) {
        j = Math.floor(Math.random() * i);
        temp = array[i - 1];
        array[i - 1] = array[j];
        array[j] = temp;
    }
}
students = ["Paul", "Jan", "Fabian D.", "Fabian K.", "Lennard", 
                            "Robin", "Angelique", "Joyce", "Sarah", "Ajlin",
                            "Enes", "Leon", "Boran", "Joshua"];
shuffle(students);
document.getElementById('tot1').innerHTML = students[0];
document.getElementById('tot2').innerHTML = students[1];
document.getElementById('tot3').innerHTML = students[2];

http://jsfiddle.net/4o897kwa/1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 2015-09-13
    • 1970-01-01
    相关资源
    最近更新 更多