Перемешивание элементов массива

Я нифига не понял как это работает, но нашел такое:
[collections.arraylist]$a = 0..51
$r = ($a.count-1)..0 |% {$R = new-object random}{$R.next(0,$a.count) |%{$a[$_];$a.removeat($_)}}

Оно работает, но если мне объяснят — как, то буду счастлив =)

[collections.arraylist]$a = 0..51 # Создаем объект типа arrayList (в отличии от # обычного array у него есть метод .RemoveAt) и помещаем в него все числа # от 0 до 51 включительно $ret = # Результат сортировки мы поместим в переменную $ret ($a.count-1)..0 | % { # это некий аналог for🙂 просто выполняем операцию # столько раз, сколько элементов в массиве. % - это # просто алиас для foreach-object. # Кроме того, синтаксис foreach-object не ограничивается # одним блоком кода. foreach-object [{begin}] {process} [{end}] # блоки кода begin и end выполняются однократно, перед # и после обработки всех элементов соответственно. Блок # process выполняется для каждого элемента конвейера. $R = new-object random # Тут, перед началом обработки элементов создается # объект $R, для получения произвольных чисел }{ # теперь пошел блок process, он выполнится для каждого элемента конвейера $R.next(0,$a.count) | # Вызывается метод next объекта $R. Он выдает # произвольное число в пределах массива которое # передается по конвейеру дальше %{ # в foreach-object... $a[$_]; # теперь элемент под произвольным номером выдается в # конвейер дальше, и... $a.removeat($_) # удаляется из оригинального массива. } } # в результате на выходе будут элементы вытащенные из $a в произвольном порядке

Я бы сам наверное не понял бы такого объяснения🙂 Так что спрашивайте что непонятно🙂

Иначе можно было бы написать то же самое так:

[collections.arraylist]$Arr $Arr = 0..51 $Rnd = new-object System.Random $Result = @() for ($i = 0; $i -lt $Arr.count; $i++) { $Id = $Rnd.next(0,$Arr.count) $Result += $Arr[$Id] $Arr.RemoveAt($Id) }

комментариев 13 to “Перемешивание элементов массива”

  1. komatozo Says:

    Сенксь… Хотя второй вариант явно внятнее =)))

  2. Xaegr Says:

    Зато первый удобнее в консоли писать когда уже всё понятно🙂

  3. komatozo Says:

    «Все понятно» это не про меня =)

  4. Xaegr Says:

    Ну это пока🙂

  5. komatozo Says:

    О… Образовался еще один вопрос: как мы все это проворачиваем (в моем исходном вопросе) с одной и той же переменной $r??? $r ведь -eq $R??? =)

  6. Xaegr Says:

    Я тоже обратил внимание, поэтому и исправил🙂 Имхо это некрасиво🙂
    Но по сути $R используется только внутри конвейера, а затем уже ей присваивается результат. Поэтому и работает🙂

  7. komatozo Says:

    Тоже понял…

  8. Vadim Says:

    Операция $Result += $Arr[$Id] работает ведь не за константу?
    Массив каждый раз перевыделяется?
    Проясните этот момент, плз🙂

  9. Xaegr Says:

    2 Vadim: Да, технически создается новый массив🙂 Но вам этого не видно, и не критично при небольших размерах массива🙂

  10. Mc'key Says:

    Мой вариант (может кому понятнее будет):

    $C = $Deck.Count
    0..($C-1) | ForEach-Object {$I=$RndGen.Next($C);$Deck[$_],$Deck[$I]=$Deck[$I],$Deck[$_]}

  11. Xaegr Says:

    2 Mc’key: Отличный метод, спасибо!🙂

  12. Scripting Games: Advanced PowerShell - Event 1 « PowerShell и другие скрипты Says:

    […] В продолжение этого поста, еще одно решение для тасования массива — от Bruno […]

  13. Scripting Games: Advanced PowerShell - Event 7 « PowerShell и другие скрипты Says:

    […] массива еще стоит посмотреть вот эти два моих поста: 1, 2 и комментарии к […]


Обсуждение закрыто.

%d такие блоггеры, как: