Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Задачка по генерации чисел (https://javascript.ru/forum/misc/60372-zadachka-po-generacii-chisel.html)

рони 26.12.2015 17:42

Создание массива с уникальными данными и в указанном диапазоне
 
функция заполняет массив уникальными данными в указанном диапазоне или перемешивает исходный, если диапазон не указан заполняет от нуля по порядку.
в трёх примерах ниже генерация происходит только пять раз.(исходная длина массива)

<script>
Array.prototype.randomShuffle = function(min,max) {
  min = min || 0;
  max = ++max || this.length;
  var len = max - min;
  max = len - this.length;
  this.length = len;
    for (var a = this.length-1; 0 <= a; a--) {
       if(a < max) {break}
        var b = Math.floor(Math.random() * a),
            c = void 0 === this[b] ? (b + min) : this[b];
            this[b] = void 0 === this[a] ? (a + min) : this[a];
            this[a] = c
    }
    this.reverse();
    this.length -= max;
    return this
};
var arr = Array(5).randomShuffle();
document.write(arr+"<br>")
var arr = Array(5).randomShuffle(-100,100);
document.write(arr+"<br>")
var arr =[1,2,3,4,5].randomShuffle();
document.write(arr+"<br>")
document.write(["Собака след не взяла, Взяла", "но была убита убегающим", "след потеряла"].randomShuffle()+"<br>")
</script>

рони 26.12.2015 18:14

Deff,
не осилил

рони 26.12.2015 18:30

Deff,
ок, ничего не мешает вынести предложенный метод из прототипа в отдельную функцию, но меня твои аргументы не убедили,
по моему проще если нужно сделать arr.slice().shuffle() чем slice добавлять в функцию.

Deff 26.12.2015 18:30

function indRand(a){
     var out=[],n=a.length; a=a.slice(0);
     while (n--){out.push(a.splice(Math.floor((n+1)*Math.random()),1)[0]);}
     return out;
  }
var tim = +new Date
var arr='1234567890'.split('');

n=1000000;
while (n--){
  var b = indRand(arr);
}

alert((+new Date-tim)/1000);


Array.prototype.shuffle = function(min,max) {
  min = min || 0;
  max = ++max || this.length;
  var len = max - min;
  max = len - this.length;
  this.length = len;
    for (var a = this.length-1; 0 <= a; a--) {
       if(a < max) {break}
        var b = Math.floor(Math.random() * a),
            c = void 0 === this[b] ? (b + min) : this[b];
            this[b] = void 0 === this[a] ? (a + min) : this[a];
            this[a] = c
    }
    this.reverse();
    this.length -= max;
    return this
};

var tim = +new Date
var arr='1234567890'.split('');

n=1000000;
while (n--){
  var arr =arr.shuffle();
}

alert((+new Date-tim)/1000);

Твой Вариант значительно быстрее!
Гы, а на длинных массивах, длиной более 100, преимущество в 8 и более раз! :dance:

Deff 26.12.2015 19:22

Ксать подобная перестановка в математике обзывается
randomShuffle (Имхо более говорящее название, нативный перевод как: случайная перестановка из массива существующих)
==============================
Выложил бы на Хабре - Фишка весьма востребованная ( к примеру для массовой генерации паролей или ключей (Видел сотни вопросов про как сделать - всё примерно делали как в посте от Ruslan_xDD...
Упор делать на "быстрая!"
.

рони 26.12.2015 19:34

Deff,
randomShuffle ок :)
Array.prototype.randomShuffle = function(c, b) {
    c = c || 0;
    b = ++b || this.length;
    var a = b - c;
    b = a - this.length;
    this.length = a;
    for (a = this.length - 1; 0 <= a && !(a < b); a--) {
        var d = Math.floor(Math.random() * a),
            e = void 0 === this[d] ? d + c : this[d];
        this[d] = void 0 === this[a] ? a + c : this[a];
        this[a] = e
    }
    this.reverse();
    this.length -= b;
    return this
};
alert(Array(5).randomShuffle())

Deff 26.12.2015 23:43

Посмотри такой нюанс при max<2
var arr = Array(5).shuffle(-1,1);
Либо нун пояснить про диапазон c, b

рони 27.12.2015 11:16

Deff,
защиты от дурака я не встраивал :)

рони 27.12.2015 12:07

:write:
чуть сократил ещё :)
Array.prototype.randomShuffle = function(c, b) {
    c = c || 0;
    b = ++b || this.length;
    var a = b - c;
    b = a - this.length;
    this.length = a--;
    for (; 0 <= a && !(a < b); a--) {
        var d = Math.floor(Math.random() * a),
            e = void 0 === this[d] ? d + c : this[d];
        this[d] = void 0 === this[a] ? a + c : this[a];
        this[a] = e
    }
    this.reverse();
    this.length -= b;
    return this
};
alert( Array(5).randomShuffle(-1,1))//заполнение пустого массива идёт на длину указанного диапазона от min до max
alert( Array(5).randomShuffle(-10,10))

Deff 27.12.2015 13:24

рони, Т.е, если массив длинной 5, разность мин-мах диапазона проставленного в параметрах [a,b] вызова метода randomShuffle(a,b) должна быть не меньше пяти, для полного заполнения массива уникальными значениями ( Я задаю типовые вопросы, согласно любому представления нового скрипта на Хабре, вот я ап чём) Для тренировки :yes:


Часовой пояс GMT +3, время: 00:00.