2016-03-04 73 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 –