2011-05-30 42 views
4

我想從C#轉換下面的算法到VB.NET和VB.NET我沒有產生相同的結果作爲我的C#算法,有人可以告訴我在哪裏我在轉換中出錯了?從C#轉換算法到VB.NET失敗

public static IEnumerable<T[]> Combinations<T>(this IEnumerable<T> elements, int k) 
{ 
    List<T[]> result = new List<T[]>(); 

    // single combination 
    if (k == 0) 
    { 
     result.Add(new T[0]); 
    } 
    else 
    { 
     int current = 1; 
     foreach (T element in elements) 
     { 
      //combine each element with k-1 combinations of subsequent elements 
      result.AddRange(elements 
       .Skip(current++) 
       .Combinations(k - 1) 
       .Select(combination => (new T[] { element }).Concat(combination).ToArray()) 
       ); 
     } 
    } 
    return result; 
} 

這是我在VB.NET中已經有了:

<Extension()> 
Public Function Combinations(Of T)(ByRef elements As IEnumerable(Of T), ByVal k As Integer) As IEnumerable(Of T()) 

    Dim result As New List(Of T())() 

    'single combination' 
    If k = 0 Then 
     result.Add(New T(-1) {}) 
    Else 
     Dim current As Integer = 0 

     For Each element As T In elements 
      'combine each element with k - 1 combinations of subsequent elements' 
      Dim local As T = element 
      result.AddRange(elements.Skip(current = current + 1).Combinations(k - 1).Select(Function(combs) (New T() {local}).Concat(combs).ToArray())) 
     Next 
    End If 

    Return result 
End Function 

東西是錯的,但我不知道,我猜問題是在lambda地方。

任何人都可以指出我的轉換錯了嗎?

+6

你有原始方法的單元測試嗎?如果沒有,請寫一些,然後在轉換的版本上運行它們。 – ashes999 2011-05-30 08:41:37

回答

2

使用代碼轉換器...

<System.Runtime.CompilerServices.Extension> _ 
Public Shared Function Combinations(Of T)(elements As IEnumerable(Of T), k As Integer) As IEnumerable(Of T()) 
    Dim result As New List(Of T())() 

    ' single combination 
    If k = 0 Then 
     result.Add(New T(-1) {}) 
    Else 
     Dim current As Integer = 1 
     For Each element As T In elements 
      'combine each element with k-1 combinations of subsequent elements 

      result.AddRange(elements.Skip(System.Math.Max(System.Threading.Interlocked.Increment(current),current - 1)).Combinations(k - 1).[Select](Function(combination) (New T() {element}).Concat(combination).ToArray())) 
     Next 
    End If 

    Return result 
End Function 
+0

這是做一些似乎不是在原來的代碼...'最大(Interlocked.Increment(當前),當前 - 1)'一個... – 2011-05-30 08:54:13

+0

@Merlyn:它似乎工作,但是... – 2011-05-30 08:54:47

+0

這相當於'current ++'。 – 2011-05-30 08:55:16

0

我對VB沒有專家可言,但問題可能源於兩種:

current = current + 1是不一樣的current++。它(基本上)與++current相同。這些有不同的行爲。

由於VB不直接支持內嵌後增量運營商,最接近無bug的實現我能想到的是(在C#中,因爲我不知道VB):

int current = 0; 
Func<int> getCurrentThenIncrement =() => 
{ 
    int previous = current; 
    current = current + 1; 
    return previous; 
}; 

// ... 
.Skip(getCurrentThenIncrement()) 

或者,這可能源於:

Public Function Combinations(Of T)(ByRef elements ... 

當我使用.net反射來看看它和「轉換」它VB,elements似乎ByVal

0

據我所知,根本不需要就地增加電流。只需在 Linq表達後遞增。另一方面,您應該使用1初始化current,與C#中的一樣。

此外,您的「基本案例」有點奇怪,你可以這樣寫:

result.Add(New T() { }) 

沒有必要爲-1

0

我沒有手頭上有編譯器檢查,但我想它轉換這樣的:

<Extension()> 
Public Function Combinations(Of T)(elements As IEnumerable(Of T), k As Integer) As IEnumerable(Of T()) 

    Dim result As New List(Of T())() 

    ' single combination 
    If k = 0 Then 
     result.Add(New T() {}) 
    Else 
     Dim current As Integer = 1 
     For Each element As T In elements 
      'combine each element with k-1 combinations of subsequent elements 
      result.AddRange(elements 
       .Skip(PostfixInc(current)) 
       .Combinations(k - 1) 
       .Select(Function(combination) (New T() { element }).Concat(combination).ToArray()) 
       ) 
     Next 
    End If 
    Return result 

End Function 

Private Function PostfixInc(ByRef value As Integer) As Integer 

    Dim currentValue = value 
    value += 1 
    Return currentValue 

End Function 

這是直接爲我現在能想到的每一個語法元素的轉化。一旦你有它的工作,然後考慮清理它(例如嘗試從LINQ表達式去除副作用)。

編輯:

從您的代碼差異:

  • New T(-1) {}應該New T() {}
  • current應該初始化爲1而不是0。
  • Skip(current = current + 1)不會做你想做的。實際上,它什麼都不做,因爲current = current + 1是一個布爾表達式,總是會計算爲false。如果選項strict關閉,VB.NET將默認地將false轉換爲0,如果選項strict處於打開狀態,則會拋出編譯器錯誤。