Реализация этого как генератора делает его довольно приятным для работы. Обратите внимание: эта реализация отличается от той, которая требует, чтобы весь входной массив сначала перетасовался.
Эта функция
blockquote>sample
работает лениво, предоставляя вам 1 случайный элемент за итерацию доN
предметов, которые вы запрашиваете. Это хорошо, потому что, если вам просто нужно 3 элемента из списка 1000, сначала вам не нужно касаться всех 1000 элементов.
// sample :: Integer -> [a] -> [a] const sample = n => function* (xs) { let ys = xs.slice(0); let len = xs.length; while (n > 0 && len > 0) { let i = (Math.random() * len) >> 0; yield ys.splice(i,1)[0]; n--; len--; } } // example inputs let items = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; // get 3 random items for (let i of sample(3) (items)) console.log(i); // f g c // partial application const lotto = sample(3); for (let i of lotto(numbers)) console.log(i); // 3 8 7 // shuffle an array const shuffle = xs => Array.from(sample (Infinity) (xs)) console.log(shuffle(items)) // [b c g f d e a]
Я решил реализовать
sample
способом, который не мутирует входной массив, но вы можете легко утверждать, что мутирующая реализация благоприятна.Например,
shuffle
функция может захотеть изменить исходный массив ввода. Или вы можете попробовать с одного и того же входа в разное время, каждый раз обновляя вход.
// sample :: Integer -> [a] -> [a] const sample = n => function* (xs) { let len = xs.length; while (n > 0 && len > 0) { let i = (Math.random() * len) >> 0; yield xs.splice(i,1)[0]; n--; len--; } } // deal :: [Card] -> [Card] const deal = xs => Array.from(sample (2) (xs)); // setup a deck of cards (13 in this case) // cards :: [Card] let cards = 'A234567890JQK'.split(''); // deal 6 players 2 cards each // players :: [[Card]] let players = Array.from(Array(6), $=> deal(cards)) console.log(players); // [K, J], [6, 0], [2, 8], [Q, 7], [5, 4], [9, A] // `cards` has been mutated. only 1 card remains in the deck console.log(cards); // [3]
sample
больше не чистая функция из-за входной мутации массива, но в определенных обстоятельствах (продемонстрировано выше) это может иметь больше смысла.Еще одна причина, по которой я выбрал генератор вместо функции, которая просто возвращает массив, потому что вы можете продолжить выборку до определенного условия.
Возможно, я хочу, чтобы первое простое число из списка из 1 000 000 случайных чисел.
- «Сколько должен ли я пробовать? » - вам не нужно указывать
- « Должен ли я сначала найти все простые числа, а затем выбрать случайное число? » - Нет.
Поскольку мы работаем с генератором, эта задача тривиальна
const randomPrimeNumber = listOfNumbers => { for (let x of sample(Infinity) (listOfNumbers)) { if (isPrime(x)) return x; } return NaN; }
Это будет непрерывно отображать 1 случайное число за раз,
x
, проверьте, является ли он простым, а затем возвратитеx
, если это так. Если список чисел исчерпан до того, как найдено штрих, возвращаетсяNaN
.Примечание:
Этот ответ был первоначально разделен по другому вопросу, который был закрыт как дубликат этого. Поскольку он сильно отличается от других предлагаемых здесь решений, я решил поделиться им и здесь
вы можете заглянуть в statsvn , для которого просто нужна извлеченная рабочая копия и подключение к репо. Он извлечет массу информации из вашего репозитория. Это java-проект, который будет работать на всех архитектурах. Он также будет создавать тепловые карты, LOC-графики и другие изображения для визуализации данных.
Я попробовал svnplot на большом репозитории, он генерирует хорошие отчеты HTML со следующими графиками:
Требуется Python и несколько библиотек Python.
Я также использовал StatSVN. Он предоставляет полезную статистику (посмотрите пример выходных данных для Ant ), но он требует, чтобы вы уже выполнили svnlog хранилища и имели рабочую копию, извлеченную для выполнения анализа.