2010-07-25 97 views
2

問題很簡單 - 它接收數組作爲它的參數說,我得到了功能,C#陣列的問題(分)

void calc(double[] data) 

怎麼辦「分裂」這個數據在兩個子陣列,並傳遞給子功能,這樣

calc_sub(data(0, length/2)); 
cals_sub(data(length /2, length /2)); 

我希望,你得到了主意 - 在C++中,我會寫這篇

void calc(double * data, int len) 
{ 
    calc_sub(data, len/2); //this one modifies data!! 
    calc_sub(data + len/2, len/2); //this one modifies data too!! 
} 

如何做同樣的在C#中不不必要的記憶複製? 我在這裏需要2個內存拷貝。 1)從數據到分割數據 2)calc_sub 3)從分割數據返回到數據!這是時間和內存的巨大浪費!

回答

2

視做什麼calc_sub,你可以做一個IEnumerable的類,它需要的陣列和遍歷數組的某一部分。類似於ArraySegment,但是better

5

簡短的回答是,要獲得一個子數組,你必須創建一個新的數組並複製元素......或者如果你使用的是C++,那麼你就是memcpy。

現在,爲什麼不採取偏移/計數方法? 致電calc_sub(blargh[] array)時,請使用calc_sub(blargh[] array, int offset, int count)

這基本上是傳遞指向start/half-pos元素的指針並告訴函數只處理數組一半數組元素的c#方法。


我要指出,除非你有巨大的雙數組時,你真的不應該擔心這一點。 64位= 8個字節。即使你有1000個元素的陣列,那就是8000字節,〜8kB的存儲器,你將在不到一秒的時間內完成所有的空間......

現在,在可能的情況下保存內存總是一個好主意,但我認爲這是過早的優化。

我還應該注意數組是通過引用傳遞的,因爲它們實際上是對象,而不是整數或字符串,所以這種方法是最好的內存方式[它不復制數組;它給出了類似於指向數組對象的指針],但是它的作用是有限的,因爲修改函數中的數組將修改在函數調用之外傳遞的數組。

+0

噸的代碼使用「那個」方法。複製作品總是,但沒有任何「更聰明」的解決方案? – 2010-07-25 10:19:12

+0

我不會問這個,如果表現不會是一個問題。 – 2010-07-25 10:39:15

+0

+1:過早優化 – surfasb 2011-12-06 05:05:34

8

最簡單的就是可能使用LINQs TakeSkip擴展方法:

int half = data.Length/2; 
double[] sub1 = data.Take(half).ToArray(); 
double[] sub2 = data.Skip(half).ToArray(); 
+0

易於閱讀的解決方案,但我很確定它很慢,因爲tak,skip和ToArray可能導致集合的簡單迭代,導致原始數據的兩次完整迭代。如果原始數據的大小很低或時間不是問題,這是一個很好的可讀解決方案 – 2010-07-25 10:37:36

+0

速度快嗎? CLR知道,如何優化這些東西? – 2010-07-25 10:39:47

+1

我總是嘗試編寫可讀的代碼,並稍後執行負載測試以驗證性能是否受損。如果是這種情況,那麼重構。 – 2010-07-25 10:40:24

1

來吧,這樣寫你自己的子陣列功能:

public static class ArrayExtensions 
{ 
    T[] SubArray<T>(this T[] arr, int startIndex,int count) 
    { 
    var sub = new T[count]; 
    Array.Copy(arr,startIndex,sub,o,count); 
    return sub; 
    } 
} 

,然後你可以使用它像:

void calc(double[] data) 
{ 
    var half = data.Length /2; 
    data.SubArray(0, half)); 
    data.SubArray(half , half)); 
} 
+0

已經在我的'public static class Extentions'中了......我認爲必須有。 – Warty 2010-07-25 10:37:00

+0

這個想法是,calc_sub不僅可以使用數據,還可以返回數據! – 2010-07-25 10:40:48

+0

@ 0xDEAD BEEF,但是calc sub返回一個由傳遞數組計算的值,對吧?我們真的不知道calc_sub是幹什麼的,所以我們不可能提供100%針對你的建議;我們猜測你的情況是什麼。 – Warty 2010-07-25 10:43:15

1

如果你可以讓calc_sub方法採取IEnumerable<double>代替double[],可以使用擴展方法創建返回數組的一部分的表達式:

void calc(double[] data) { 
    int half = data.Length/2; 
    calc_sub(data.Take((half)); 
    calc_sub(data.Skip(half)); 
} 

這樣您就不必將數據複製到新數組,表達式將從原始數組中返回項目。

+0

速度快嗎?調用IEnumberable.value而不是直接訪問數組? – 2010-07-25 10:43:26

+0

它速度相當快,但速度不如直接訪問速度快,但您是否知道性能問題? – 2010-07-25 11:01:37