11
votes

Comment utiliser Java Collections.shuffle () sur un tableau Scala?

J'ai un tableau que je veux permuter au hasard. En Java, il y a une méthode collections.shuffle () pouvant mélanger les éléments d'une liste de manière aléatoire. Il peut également être utilisé sur un tableau:

// Fisher-Yates shuffle, see: http://en.wikipedia.org/wiki/Fisher–Yates_shuffle
def shuffle[T](array: Array[T]): Array[T] = {
    val rnd = new java.util.Random
    for (n <- Iterator.range(array.length - 1, 0, -1)) {
        val k = rnd.nextInt(n + 1)
        val t = array(k); array(k) = array(n); array(n) = t
    }
    return array
}


2 commentaires

Notez que Shuffling de cette manière ne fonctionne que pour les tableaux de types de référence.


@StarBlue: Oui, la version Java ne fonctionne que pour les tableaux de types de référence. Ma propre méthode Scala Shuffle () fonctionne également avec des matrices Scala avec des primitives.


3 Réponses :


6
votes
scala> val a = Array[java.lang.Integer](1, 2, 3)
a: Array[java.lang.Integer] = Array(1, 2, 3)

scala> val b = java.util.Arrays.asList(a:_*)
b: java.util.List[java.lang.Integer] = [1, 2, 3]

scala> java.util.Collections.shuffle(b)

scala> b
res50: java.util.List[java.lang.Integer] = [2, 1, 3]

scala> java.util.Collections.shuffle(b)

scala> b
res52: java.util.List[java.lang.Integer] = [3, 1, 2]

2 commentaires

Merci. Mais cela ne fonctionne pas pour un réseau Scala avec des entiers - il en résulte une clastingexception, car la matrice ne peut pas être lancée à un réseau Java d'objets.


@Jesper pour les collections.shuffle () Pour fonctionner, assurez-vous que la matrice contient des références d'objet et non des valeurs primitives. (Scala.int -> Java.Lang.Integer, scala.long -> Java.lang.long, etc.) J'ai modifié la réponse pour souligner ce point.



5
votes

Pour répondre à la "Ce qui se passe exactement ici?" Partie:

Lorsque vous dites java.util.arrays.Aslist (a) Vous appelez une méthode Java statique qui est définie pour prendre un nombre variable d'arguments (la syntaxe Vararg ... en Java): P >

public static <T> List<T> asList(T... a) 


0 commentaires

6
votes

Il semble que Scala fait quelque chose de différent de Java quand il s'agit de Varargs. Au moins, je ne peux pas obtenir ce tableau trop mélangé à l'essai. Soi-disant, le shuffle de la liste Shufflerait le tableau car la liste est sauvegardée. Eh bien, il semble que Scala créerait un tableau neuf em> lorsque vous passez des arguments de Vararg à Java, rendant donc l'exemple susmentionné inutile.

scala> scala.util.Random.shuffle(a)
res32: Sequence[Int] = Array(1, 2, 3)

scala> scala.util.Random.shuffle(a)
res33: Sequence[Int] = Array(2, 1, 3)

scala> scala.util.Random.shuffle(a)
res34: Sequence[Int] = Array(3, 2, 1)


6 commentaires

Daniel, si je le fais: Val A = Array ("A", "B", "C") Java.Util.Collections.shauffe (Java.Util.Arrys.Aslist (A: _ *)) Alors mon tableau Scala Est-ce que vous soyez mélangé. Et si je fais un tableau d'INT au lieu de cordes, je reçois une exception classique.


Et merci pour la pointe sur SCALA 2.8, il y aura donc une méthode de shuffle () dans la bibliothèque en 2.8. Bien sûr, il renvoie un nouveau tableau, c'est la manière fonctionnelle typique de la programmation.


@Daniel je pense que vous utilisez 2.8.0 Rem. Essayez vos exemples dans 2.7.5 et vous verrez des différences de vos résultats. Apparemment, 2.8.0 génère un nouveau SEQ lorsqu'il voit ": _ *" Mais 2.7.5 vient simplement entoure un SEQ autour du tableau.


Je am en utilisant une version 2.8.0, et pas particulièrement à jour à cela. De votre réponse, j'ai rassemblé qu'il y avait une différence. Je me demande simplement si cela mérite un bogue sur Bug-Traq.


Je n'ai pas trouvé de bug ouvert, alors j'ai ouvert 2250 à ce sujet.


util.random.shauffe (a) ne semble pas fonctionner dans 2.9.1 - I Obtenir Erreur: Type déduit Arguments [int, Array] Ne vous conformez pas aux limites de paramètres de type de méthode [T, CC [x] <: TraversableOnceC [x]] :(