2010-01-24 18 views
5

Mein oberstes Ziel ist es, den folgenden Code in Python in C# umzuwandeln, aber ich würde es gerne selbst machen, indem ich die Python-Syntax lerne. Ich verstehe, dass der Code rekursiv ist.Python zu C# Code Erklärung

Der Code erzeugt Polynome Grad n mit k Variablen. Genauer gesagt die Liste der Exponenten für jede Variable.

def multichoose(n,k): 
    if k < 0 or n < 0: return "Error" 
    if not k: return [[0]*n] 
    if not n: return [] 
    if n == 1: return [[k]] 
    return [[0]+val for val in multichoose(n-1,k)] + \ 
     [[val[0]+1]+val[1:] for val in multichoose(n,k-1)] 

Hier ist die Umwandlung ich bisher haben:

public double[] MultiChoose(int n, int k) 
{ 
    if (k < 0 || n < 0) 
    { 
     throw new Exception(); 
    } 

    if (k == 0) 
    { 
     return [[0]*n]; // I have no idea what the [[0]*n] syntax means 
    } 

    if (n == 0) 
    { 
     return new double[0]; // I think this is just an empty array 
    } 

    if (n == 1) 
    { 
     return new double[1] {k}; // I think this is just an empty array 
    } 

    //Part I don't understand 
    return [[0]+val for val in MultiChoose(n-1,k)] + \ 
     [[val[0]+1]+val[1:] for val in MultiChoose(n,k-1)] 
} 

Meine Frage ist: Wie konvertiere ich das Python-Code?

+0

Also, was ist Ihre Frage? –

Antwort

3

würde ich LINQ in C# verwenden Sie den Code zu übersetzen:

  • [] ist die leere Liste.

    Enumerable.Empty<T>() 
    
  • [x] ist die Liste mit einem einzigen Artikel, x.

    Enumerable.Repeat(x, 1) 
    
  • [[0]*n] ist die Liste mit der Liste n Kopien von 0.

    Enumerable.Repeat(Enumerable.Repeat(0, n), 1) 
    
  • [X for Y in Z] ist eine Liste Verständnis enthält.

    from Y in Z select X 
        - or - 
    Z.Select(Y => X); 
    
  • X + Y (wobei X und Y Listen sind) ist die Liste Verkettung.

    Enumerable.Concat(X, Y) 
    

Die Signatur von MultiChoose wäre:

public IEnumerable<IEnumerable<double>> MultiChoose(int n, int k); 
+0

Nice =) Ist es möglich, dies auch mit Generics zu tun, d. H., Enumerable '(oder' IEnumerable '') anstelle von 'Enumerable' zu ​​verwenden? –

+0

Enumerable ist eine statische Klasse. Es hat generische Methoden, die IEnumerable 's erzeugen (ich habe die generischen Typparameter weggelassen, wo sie abgeleitet werden können), also ja. – dtb

+0

Ich denke, Sie haben die [[0] * n] falsch, es sollte Enumerable.Repeat (Enumerable.Repeat (0, n), 1), auch die äußere Wiederholung möglicherweise überhaupt nicht notwendig sein. –

1

[0] * n gibt eine Liste mit n 0 s zurück. [] ist eine leere Liste. [[k]] ist eine Liste, die eine Liste enthält, die k enthält.

Der letzte Teil verwendet List Comprehensions. Die Grundformen einer Liste Verständnis sind:

[<new value> for <name> in <sequence>] 
[<new value> for <name> in <sequence> if <condition>] 

Es schafft eine neue Liste mit den neuen Werten jedes Mal, wenn die optionale Bedingung wahr enthalten ist.

1

Einige Kommentare:

Pythons return "Error" ist eine Ausnahme nicht zu werfen. Es gibt den String-Wert "Error" zurück.

Pythons if not k: ist nicht äquivalent zu if (k == 0) es gibt mehr Dinge, die "nicht" sind, wie leere Listen, der None-Wert usw. (das kann in diesem Fall keinen Unterschied machen).

Pythons foo = [for x in bar] ist ein Listenverständnis.Es ist äquivalent zu:

foo = [] 
for x in bar: 
    foo.append(x) 
1

ich diese faszinierende und nach einiger-Hilfe mit dem Python-Code zu verstehen ich es einen Stich nahm. C# 3.0 und .NET Framework 3.5 benötigt.

public static IEnumerable<IEnumerable<int>> MultiChoose(int n, int k) 
{ 
    if (k < 0 || n < 0) throw new Exception(); 
    if (k == 0) return Enumerable.Repeat(Enumerable.Repeat(0, n), 1); 
    if (n == 0) return Enumerable.Repeat(Enumerable.Empty<int>(), 0); 
    if (n == 1) return Enumerable.Repeat(Enumerable.Repeat(k, 1), 1); 

    return (from val in MultiChoose(n - 1, k) select new [] { 0 }.Concat(val)) 
     .Concat(from val in MultiChoose(n, k - 1) select new [] { val.First() + 1 }.Concat(val.Skip(1))); 
} 

Hier ist eine Version in Ruby

def multichoose(n,k) 
    if k<0 || n<0: raise "Error" end 
    if k==0: return [[0]*n] end 
    if n==0: return [] end 
    if n==1: return [[k]] end 
    multichoose(n-1,k).map{|val| [0]+val} + \ 
    multichoose(n,k-1).map{|val| [val.first+1]+val[1..-1]} 
end 

und einige Ausgangs Beispiele:

>> multichoose(2,2) 
=> [[0, 2], [1, 1], [2, 0]] 
>> multichoose(3,2) 
=> [[0, 0, 2], [0, 1, 1], [0, 2, 0], [1, 0, 1], [1, 1, 0], [2, 0, 0]] 
>> multichoose(3,3) 
=> [[0, 0, 3], [0, 1, 2], [0, 2, 1], [0, 3, 0], [1, 0, 2], [1, 1, 1], [1, 2, 0], [2, 0, 1], [2, 1, 0], [3, 0, 0]] 
+0

+1 - sehr nett. – dtb