2016-03-04 43 views
0

我正在寻找从文本文件中拉出5个“随机”行,而不重复任何。文本文件中的每一行都有html代码,可以插入到侧面菜单中。我已经阅读了Fisher-Yates shuffle,但不知道如何将其与JavaScript结合使用。目前我有以下抛出一个错误:使用Txt文件的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(); 

<div id="random-content"><script src="content.js"></script></div> 

错误:

content.js:19遗漏的类型错误:targetHTML.contains不是functionrequest.onload @内容。 js:19

+0

尝试用'.indexOf()'替换'.contains()'if'condition – guest271314

回答

-1
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(); 
+0

Fisher-Yates不执行重复/唯一检查。 – naomik

+0

@naomik请重读他的问题:我正在从文本文件中拉出5个“随机”行,而不是重复任何。 我的解决方案解决了他的错误,并通过对代码的最小修改来完成他的问题。费舍尔耶茨只是他正在考虑实施的一些东西,但还没有开始。 –

+0

您可以抽取5条随机线,而无需进行不必要的重复/独特检查。如果原始代码不好,“对其代码的最小更改”不是一个有价值的目标。这种方法很懒,imo。原始代码需要这么多工作,几乎每一行都应该重新工作。是的,需要花费大量的精力来解释为什么它需要重新工作,但是你不会帮助初学者编写错误的代码或者保留他们已经编写的错误代码。 – naomik

0

好的,所以费希尔 - 耶茨洗牌作品的方式是

  • 得到一个随机索引,r,从输入阵列
  • 从输入阵列的输入阵列到输出数组
  • remove元素r拷贝元件r
  • 重复n次,其中n是输入数组的长度

在循环结束时,输出将是e的混洗副本修改输入数组。

我打算浏览一下小问题:这个算法不应该改变输入数组。相反,它应该保持输入数组不变,并返回一个新的数组,它是输入数组的混洗副本。 (你可以在下面的实现中看到这是如何完成的)。因此,了解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] 

还有的个体行为,你就会明白:对于1价格4种功能。在我看来,这是一个更好的解决问题的方法,因为每个函数都是有用的,因此可以在多个地方使用。拥有许多小的可重用功能将大大减少您将来必须完成的工作量。


由于所有这些复杂性都很好地划分了,我们来看看你的最终代码是什么样的。

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请求,或更好,使用图书馆。用手书写它们非常麻烦并且容易出错。大多数人使用jQuery,但最近我一直在寻找axios

+0

你确定你已经仔细阅读答案吗? –

+0

@SirajHussain wups,我在那里有一个小错字^ _ ^。我有'.splice'我想要'.slice'。谢谢你的鹰眼。 – naomik

+0

我真的很欣赏你花在你的回复naomik上的时间。我不是代码编写者,你的回应对我来说有点淹没,因为我只需要一个脚本的简单解决方案,它不会经常使用,而且可以轻松集成。抛出你的代码我收到: content.js:14 Uncaught ReferenceError:sample is not definedrequest.onload @ content.js:14 –