2012-04-21 47 views
4

我自己是LINQ的忠實粉絲。簡潔的藝術反映在LINQ中。同樣在.Net中,我們說LINQ是循環之前的一步,或者我們可以說LINQ是循環++。可以要求LINQ跳過/保留特定索引嗎?

但這真的是這樣嗎?

爲什麼我正在判斷是因爲我試圖將這個循環代碼轉換爲LINQ,但感到困惑,做LINQ跳過/離開索引?

double[] NMD = {3.0, 5.0, 6.0, 65.0, 34.0, 3.0, 5.0, 6.0, 65.0, 34.0, 3.0, 5.0, 6.0, 65.0, 34.0 }; 

for(int i=1; i<NMD.Length-1; i+=2) 
    NMD[i] = NMD[i]/10; 

我在這裏要求循環從索引1開始,在倒數第二個值停止,也被2跳的值,所以我們可以做到這一點的LINQ。國際海事組織我不這麼認爲但是我會很樂意被證明是錯誤的。

+0

如果您需要運行更新,您的for循環是最乾淨的解決方案。 – dasblinkenlight 2012-04-21 10:43:09

+0

我同意@dasblinkenlight,但是除此之外,如果你已經有了工作代碼,那麼只需要使用LINQ就不值得重寫它。 – 2012-04-21 10:44:35

+0

@Ian:我不同意。在這種情況下,原始代碼很可能是* buggy *(因爲它不修改最後一個元素,即使它有一個奇怪的索引!)以更多功能樣式重寫代碼可以幫助消除這些問題(因爲您聲明期望的輸出,而不是實現它的算法)。 – 2012-04-21 10:46:31

回答

5

您可以測試指標中Select並據此選擇你的行動:

NMD = NMD.Select((x, i) => i % 2 == 1 && i < NMD.Length - 1 ? x/10 : x).ToArray(); 
// => { 3, 0.5, 6, 6.5, 34, 0.3, 5, 0.6, 65, 3.4, 3, 0.5, 6, 6.5, 34 } 

然而,正如你可能已經在尋找這個語句的大小想通了,LINQ是的概念改進這裏,因爲你只能用它創建新的序列,而不能改變現有的序列。

也就是說,在我看來,for循環很好,實際上更具可讀性。您不應該說「LINQ是循環++」,您應該將其細化爲「LINQ是序列生成++」或「只讀迭代++」。

如果你想高效地使用LINQ,你必須以更有效的方式重新思考和重新設計你的代碼(例如使用不可變的數據結構),而不是用LINQ表達式替換每個for循環。如果你這樣做並且理智的話,你可以提高代碼的質量,並且使交換機並行執行在將來更少問題。

0

您只能選擇具有奇數索引的項目,並且NMD.Where((x,i) => i % 2 == 1),但不能更新數組中的值。

+0

從1開始到倒數第二個怎麼樣? – 2012-04-21 10:42:04

1
var NMD = new[] {3.0, 5.0, 6.0, 65.0, 34.0, 3.0, 5.0, 6.0, 65.0, 34.0, 3.0, 5.0, 6.0, 65.0, 34.0 }; 
NMD = NMD.Select((n, i) => i % 2 == 1 ? n/10 : n).ToArray(); 
+0

這隻會丟掉第一個和最後一個值。 – 2012-04-21 11:18:22

+0

是的,你是對的。根據您的評論進行編輯。如果數組長度是奇數,你也不需要檢查是否 user1339260 2012-04-21 11:38:19

+0

陣列不一定是奇數長度,所以你必須檢查反正。我不確定它是否真的打算最後一個項目不受影響,但... – 2012-04-21 11:39:31

0

Linq對於這類任務並不是真正的最佳工具 - 只是其中的一部分改變了數據。但是,如果你真的想,你可以做這樣的:

NMD = NMD.Select((x, i) => 
{ 
    if (i < 1 || i >= NMD.Length - 1 || (i % 2)==0) 
     return x; 
    else 
     return x/10; 
}).ToArray(); 

請記住,LINQ,你會不會改變現有的順序,你會用一個新的更換。

相關問題