2016-03-04 4 views
0

Я ищу, чтобы вытащить 5 «случайных» строк из текстового файла, не повторяя никаких. Каждая строка из текстового файла содержит html-код, который будет вставлен в боковое меню. Я прочитал о перетасовке Фишера-Йейтса, но не уверен, как включить его таким образом с помощью javascript. В настоящее время у меня есть следующий метание ошибка:Javascript Shuffle Array из файла Txt

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 Uncaught TypeError: targetHTML.contains не functionrequest.onload @ содержание. JS: 19

+0

Попробуйте заменить '.indexOf()' 'для .Contains()' в 'if' состоянии – 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 случайных строк, не выполняя ненужных дубликатов/уникальных проверок. «минимальные изменения в его коде» не стоит того, если исходный код плохой. Этот подход ленив, имо. Исходный код нуждается в такой большой работе здесь, что нужно переделать почти * каждую * строку. Да, это требует много усилий, чтобы объяснить * почему * его нужно переработать, но вы не делаете никаких выгод, помогая новичкам писать плохой код или оставлять плохой код, который они уже написали. – naomik

0

ОК, так как Fisher-Yates перетасовать работы является

  • получить случайный индекс, r, из входного массива
  • копия элемента r из входного массива в выходной массив
  • удалить элемент r из входного массива
  • повтор n раз, где n - длина входной матрицы

К концу цикла выход будет перетасованной копией e ntire input array.

Я собираюсь взглянуть на одну небольшую ошибку: этот алгоритм не должен мутировать входной массив. Вместо этого он должен оставить входной массив нетронутым и вернуть новый массив, который является перетасованной копией входного массива. (Вы можете видеть, как это делается в моей реализации ниже).

Так зная, как работает Fisher-Yates, в вашем случае, мы не должны перетасовать массив весь так как вы знаете, прежде чем руки, что вы хотите только N элементы.

Давайте сначала посмотрим на ваш вход.

var fileContent = this.responseText; 
var fileContentLines = fileContent.split('\n'); 

OK, безупречный. Вы определили входной массив, 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 запросов, или лучше, используйте библиотеку. Написание их вручную чрезвычайно громоздко и подвержено ошибкам. Большинство людей используют jQuery, но в последнее время я доставая axios

+0

Вы уверены, что внимательно прочитали ответ? –

+0

@ SirajHussain wups, у меня была небольшая опечатка там^_ ^. У меня было '.splice', где я намеревался' .slice'. Спасибо за глаза орла. – naomik

+0

Я действительно ценю время, которое вы потратили на свой ответ naomik. Я не писатель кода, и ваш ответ немного наводняет меня, так как мне просто нужно простое решение для скрипта, который не будет использоваться слишком часто, чтобы его можно было легко интегрировать. Выбрасывая код, я получаю: content.js: 14 Uncaught ReferenceError: sample не указанrequest.onload @ content.js: 14 –