ОК, так как 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
Попробуйте заменить '.indexOf()' 'для .Contains()' в 'if' состоянии – guest271314