2009-11-16 5 views
0

Quelle serait la traduction correcte de la méthode Python suivante en Ruby?traduire la méthode python en ruby ​​

def uniqueCombinations(self, items, n): 
    """ 
    items: list of elements 
    n: number in a group 
    """ 
    if n == 0: 
     yield [] 
    else: 
     for i in range(len(items)-n+1): 
      for cc in uniqueCombinations(items[i+1:],n-1): 
       yield [items[i]]+cc 

Ce que je veux faire est d'appeler

uniqueCombinations(['01', '02', '03'], 2) 

et obtenir

[['01', '02'], ['01', '03'], ['02', '03']] 

C'est ce que j'ai jusqu'à présent.

def uniq_c(items, n) 
    if n == 0 
    yield [] 
    else 
    puts items.inspect 
    range_max = items.length-n+1 
    for i in (0...range_max) 
     u = uniq_c(items[(i+1)..-1], n-1) { |x| x } 
     u.each do |cc| 
     yield [items[i]] + cc 
     end 
    end 
    end 
end 

mais je reçois ceci:

in `+': can't convert Fixnum into Array (TypeError) 
+1

La version python pourrait être écrite comme ceci: 'return itertools.combinations (articles, n) ' – nosklo

Répondre

0

D'abord, il serait préférable de le faire en tant que méthode de la classe Array. Ensuite, vous pouvez corriger votre erreur en remplaçant [items[i]] + cc par [items[i]] + [cc]. Troisièmement, voici une autre mise en œuvre que je traînais, voyez ce que vous en pensez. Il crée un tableau de permutations représentées par des index, puis mappe chaque index à sa valeur.

class Array 
    def combinations(n) 
    perms = [] 
    a = (0...n).to_a 
    while perms.push a.dup 
     break if a.increment!(a.length - 1, self.length-1).nil? 
    end 
    perms.map {|p| p.map {|i| self[i]} } 
    end 
    def increment!(i, max) 
    self[i] += 1 
    while self[i] > max 
     return nil if i <= 0 
     return nil if self.increment!(i - 1, max).nil? 
     self[i] = self[i - 1] + 1 
    end 
    self.dup 
    end 
end 

[1,2,3].combinations 3 # => [[1, 2, 3]] 
[1,2,3].combinations 2 # => [[1, 2], [1, 3], [2, 3]] 
[1,2,3].combinations 1 # => [[1], [2], [3]] 
[:foo,:bar,:baz,:quux,:wibble].combinations 3 
# => [[:foo, :bar, :baz], 
#  [:foo, :bar, :quux], 
#  [:foo, :bar, :wibble], 
#  [:foo, :baz, :quux], 
#  [:foo, :baz, :wibble], 
#  [:foo, :quux, :wibble], 
#  [:bar, :baz, :quux], 
#  [:bar, :baz, :wibble], 
#  [:bar, :quux, :wibble], 
#  [:baz, :quux, :wibble]] 
+0

Votre méthode fonctionne comme un charme. Je vous remercie. –

+0

Content de l'entendre! Il semble que ce soit moins efficace que le vôtre, mais plus facile à comprendre. Ou peut-être que je suis juste privé de sommeil. En tout cas, je pense qu'essayer d'utiliser 'yield 'de la même façon dans Ruby ne fonctionne pas. – jtbandes

2
yield [items[i]] + cc 

Vous essayez de concaténer un tableau ([articles [i]]) et un Fixnum (cc). Vous pouvez à la place transformer les deux en un tableau ou utiliser la méthode < < pour pousser cc sur [items [i]].

yield [items[i]] << cc 
+0

Eh, vous tapez plus vite que moi. Voter cela. –

+0

Merci. J'ai essayé '<<' mais le résultat final de la fonction me donne la plage (0..2). Cela me déconcerte. –

2

A partir de Ruby 1.8.7 partir, classe Array fournit une méthode pour afficher les combinaisons:.

irb> [ '01', '02', '03'] combinaison (2) .to_a => [["01", "02"], ["01", "03"], ["02", "03"]]

+0

Merci beaucoup pour votre contribution. –

Questions connexes