来自Txt文件的Javascript无序数组

来自Txt文件的Javascript无序数组,javascript,arrays,random,text-files,shuffle,Javascript,Arrays,Random,Text Files,Shuffle,我希望从文本文件中随机抽取5行,同时不重复任何内容。文本文件中的每一行都有html代码,可以插入侧菜单。我读过Fisher-Yates shuffle,但不确定如何以这种方式将其与javascript结合起来。目前,我有以下错误: var request = new XMLHttpRequest(); request.onload = function() { var i = 0; // get the file contents var fileContent = th

我希望从文本文件中随机抽取5行,同时不重复任何内容。文本文件中的每一行都有html代码,可以插入侧菜单。我读过Fisher-Yates shuffle,但不确定如何以这种方式将其与javascript结合起来。目前,我有以下错误:

var request = new XMLHttpRequest();
request.onload = function() {
    var i = 0;
    // get the file contents
    var fileContent = this.responseText;
    // split into lines
    var fileContentLines = fileContent.split( '\n' );

    var target = document.getElementById( 'random-testimonial' );
    var targetHTML = target.innerHTML;

    while ( i < 5 ) {
        // get a random index (line number)
        var randomLineIndex = Math.floor( Math.random() * fileContentLines.length );
        // extract the value
        var randomLine = fileContentLines[ randomLineIndex ];

        // add the random line in a div if not duplicate            
        if ( ! targetHTML.contains(randomLine) ) {
            targetHTML += randomLine;
            i += 1;
        }
    }

    target.innerHTML = targetHTML;
};
request.open( 'GET', 'content.txt', true );
request.send();
var-request=new-XMLHttpRequest();
request.onload=函数(){
var i=0;
//获取文件内容
var fileContent=this.responseText;
//分成几行
var fileContentLines=fileContent.split('\n');
var target=document.getElementById(‘随机证明’);
var targetHTML=target.innerHTML;
而(i<5){
//获取随机索引(行号)
var randomLineIndex=Math.floor(Math.random()*fileContentLines.length);
//提取值
var randomLine=fileContentLines[randomLineIndex];
//如果不重复,则在div中添加随机行
如果(!targetHTML.contains(randomLine)){
targetHTML+=随机线;
i+=1;
}
}
target.innerHTML=targetHTML;
};
打开('GET','content.txt',true);
request.send();


错误:

content.js:19未捕获类型错误:targetHTML.contains不是functionrequest.onload@content.js:19

var request=new-XMLHttpRequest();
var request = new XMLHttpRequest();
request.onload = function() {
    var i = 0;
    // get the file contents
    var fileContent = this.responseText;
    // split into lines
    var fileContentLines = fileContent.split( '\n' );

    var target = document.getElementById( 'random-testimonial' );

    var HTMLLines = [];

    while ( i < 5 ) {
        // get a random index (line number)
        var randomLineIndex = Math.floor( Math.random() * fileContentLines.length );
        // extract the value
        var randomLine = fileContentLines[ randomLineIndex ];

        // add the random line if not duplicate            
        if ( HTMLLines.indexOf(randomLine) === -1) {
            HTMLLines.push(randomLine);
            i += 1;
        }
    }

    target.innerHTML = HTMLLines.join('\n');
};
request.open( 'GET', 'content.txt', true );
request.send();
request.onload=函数(){ var i=0; //获取文件内容 var fileContent=this.responseText; //分成几行 var fileContentLines=fileContent.split('\n'); var target=document.getElementById(‘随机证明’); var htmlines=[]; 而(i<5){ //获取随机索引(行号) var randomLineIndex=Math.floor(Math.random()*fileContentLines.length); //提取值 var randomLine=fileContentLines[randomLineIndex]; //如果不重复,则添加随机行 if(htmlines.indexOf(randomLine)=-1){ 推(随机线); i+=1; } } target.innerHTML=htmlines.join('\n'); }; 打开('GET','content.txt',true); request.send();
好的,Fisher Yates shuffle的工作方式是

  • 从输入数组中获取一个随机索引,
    r
  • 将元素
    r
    从输入数组复制到输出数组
  • 从输入数组中删除元素
    r
  • 重复
    n
    次,其中
    n
    是输入数组的长度
循环结束时,输出将是整个输入数组的无序副本

我将略过一个小问题:这个算法不应该改变输入数组。相反,它应该保持输入数组不变,并返回一个新数组,该数组是输入数组的无序副本。(您可以在下面的我的实现中看到这是如何实现的)

因此,了解Fisher Yates是如何工作的,在您的情况下,我们不必洗牌整个数组,因为您事先知道您只需要
N
元素

让我们首先看看您的输入

var fileContent = this.responseText;
var fileContentLines = fileContent.split( '\n' );
好的,太好了。您已经定义了输入数组,
fileContentLines
。现在让我们做一个函数,从中采样一些随机元素

// fisher-yates sample
// • sample n elements from xs
// • does not mutate xs
// • guarantees each sampled element is unique
function sample (n,xs) {
  function loop(i, output, input, len) {
    if (i === n) return output;                   // loop exit condition
    let r = Math.floor(Math.random() * len);      // rand number between 0 and len
    return loop(                                  // continue loop
      i + 1,                                      // increment loop counter
      output.concat(input[r]),                    // copy element r from input
      input.slice(0,r).concat(input.slice(r+1)),  // remove element from input
      len - 1                                     // decrement length
    );
  }
  return loop(0, [], xs, xs.length);              // begin loop
}
好的!让我们首先用一个简单的输入来检查它

// sample 3 random inputs from numbers 1 through 10
console.log(sample(3, [1,2,3,4,5,6,7,8,9,10])); //=> [9,7,5]
太好了。现在只需在你的行数组中调用它

var result = sample(5, fileContentLines);
console.log(result); // ...

上面的代码是有效的,但我们不要到此为止。我们的代码承担了太多的责任,我们可以将一些行为分离成可重用的函数

// get rand number between 0 and n
function rand(x) {
  return Math.floor(Math.random() * x);
}

// splice of xs at index i
// • return a new output array
// • does not mutate xs
function del(i,xs) {
  return xs.slice(0,i).concat(xs.slice(i+1));
}

// fisher-yates sample
// • sample n elements from xs
// • does not mutate xs
// • guarantees each sampled element is unique
function sample (n,xs) {
  function loop(i, output, input, len) {
    if (i === n) return output;       // loop exit condition
    let r = rand(len);                // rand number between 0 and len
    return loop(                      // continue loop
      i + 1,                          // increment loop counter
      output.concat(input[r]),        // copy element r from input
      del(r,input),                   // remove element from input
      len - 1                         // decrement length
    );
  }
  return loop(0, [], xs, xs.length);  // begin loop
}

// fisher-yates shuffle
// • does not mutate xs
function shuffle(xs) {
  return sample(xs.length, xs);
}
让我们快速查看每个函数的单独行为

// generate random number between 0 and 10 (exclusive)
console.log(rand(10)); //=> 5

// delete 2nd letter from letters a through d
console.log(del(1, ['a', 'b', 'c', 'd'])); // => ['a', 'c', 'd]

// sample 3 random inputs from numbers 1 through 10
console.log(sample(3, [1,2,3,4,5,6,7,8,9,10])); //=> [9,7,5]

// shuffle entire input array
console.log(shuffle([1,2,3,4,5,6,7,8,9,10])); //=> [8,9,1,3,7,6,10,5,4,2]
现在你有了:4个功能,价格为1。在我看来,这是一个更好的解决问题的方法,因为每个函数本身都很有用,因此可以在多个地方使用。拥有大量可重用的小功能将大大减少您将来必须完成的工作量


将所有这些复杂性很好地划分开来,让我们看看最终的代码是什么样子

function createParagraph(text) {
  var p = document.createElement('p');
  p.innerHTML = text;
  return p;
}

var request = new XMLHttpRequest();
request.onload = function() {

  var fileContent = this.responseText;
  var fileContentLines = fileContent.split('\n');
  var target = document.getElementById('random-testimonial');

  sample(5, fileContentLines).map(function(testimonial) {
    var p = createParagraph(testimonial);
    target.appendChild(p);
  });
};
request.open('GET', 'content.txt', true);
request.send();

PS我强烈建议您为ajax请求编写可重用函数,或者最好使用库。手工书写极其繁琐且容易出错。大多数人使用,但最近我一直在用
.indexOf()
替换
.contains()
如果
条件Fisher-Yates不进行重复/唯一检查,请尝试使用
.indexOf()
替换
.contains()
。@naomik请重读他的问题:我希望从文本文件中随机抽取5行,但不重复任何行。我的解决方案解决了他的错误,只需对代码进行最小的更改就可以完成他的问题。Fisher Yates只是他正在考虑实现的东西,但还没有开始。你可以随机抽取5行,而不必做不必要的重复/唯一检查。如果原始代码不好,“对其代码进行最小更改”不是一个值得追求的目标。在我看来,这种方法是懒惰的。原始代码在这里需要做很多工作,几乎每一行都需要重新编写。是的,要解释为什么需要重新工作需要花很多精力,但是,帮助初学者编写糟糕的代码或保留他们已经编写的糟糕代码并没有给你带来任何好处。只是对寻求他人帮助的人缺乏努力感到无比失望。@naomik在下次发帖之前,试着了解一些人的需要。我对帮助别人解决手头的问题感兴趣,你对互联网感兴趣points@SirajHussain哎呀,我有点打字错误。我有
.splice
我想要的
.slice
。谢谢你的鹰眼。我真的很感谢你花时间回复纳奥米克。我不是一个代码编写者,你的回答让我有点不知所措,因为我只需要一个简单的脚本解决方案,这个脚本不会经常使用,可以轻松集成
function createParagraph(text) {
  var p = document.createElement('p');
  p.innerHTML = text;
  return p;
}

var request = new XMLHttpRequest();
request.onload = function() {

  var fileContent = this.responseText;
  var fileContentLines = fileContent.split('\n');
  var target = document.getElementById('random-testimonial');

  sample(5, fileContentLines).map(function(testimonial) {
    var p = createParagraph(testimonial);
    target.appendChild(p);
  });
};
request.open('GET', 'content.txt', true);
request.send();