2014-11-01 57 views
1

的名單上有這個功能,它的工作原理,並給出正確的結果:如何唯一的數字追加到字符串

<System.Runtime.CompilerServices.Extension()> 
    Public Function Unique(List As List(Of String)) As List(Of String) 
    Return List.Select(Function(x, index) x & System.Text.RegularExpressions.Regex.Replace((List.GetRange(0, index).Where(Function(y) y = x).Count + 1).ToString, "\b1\b", String.Empty)).ToList 
    End Function 

該函數將一個「2」,「3」等根據需要,對那些不是唯一的項目,使它們獨一無二。

如何在a)停留在相同的linq語句(相同的代碼行)時,b)不引入循環或c)兩次評估表達式,如在IIF語句中所需要的,我該如何移除正則表達式?

這不是Getting index of duplicate items in a list in c#的重複,因爲a)我的列表在函數期間沒有改變,b)這個問題沒有被準備好應用代碼示例所回答,在這裏我正在尋找一個特定的修復程序一個特定的代碼行。這些答案不會解決我的問題;他們不適用於此。

+0

你關心維持秩序,或者你可以使用'GroupBy'收集了所有具有相同標識符的那些然後爲每個組中的每個添加一個索引? – 2014-11-01 03:14:31

+0

是的順序很重要。這些是csv文件中的標題,它們必須匹配行值。謝謝 – toddmo 2014-11-01 23:23:15

回答

1

你可以使用GroupBy來做到這一點,如果你想保留原始訂單,你可以創建一個匿名類型來包含它,然後分組,然後按原始順序重新排序。

string[] input = new[]{ "Apple", "Orange", "Apple", "Pear", "Banana", 
          "Apple", "Apple", "Orange" }; 

    var result = input 
     // Remember the initial order 
     .Select((name, i) => new {name, i}) 
     .GroupBy(x => x.name) 
     // Now label the entries in each group 
     .SelectMany(g => g.Select((item, j) => 
      new {i = item.i, name = (j == 0 ? item.name : item.name + (j+1))})) 
     // Now reorder them by their original order 
     .OrderBy(x => x.i) 
     // Remove the order value to get back to just the name 
     .Select(x => x.name) 
     .ToList(); 


    foreach (var r in result) 
     Console.WriteLine(r); 

結果

Apple 
Orange 
Apple2 
Pear 
Banana 
Apple3 
Apple4 
Orange2 
+1

也許這很奇怪,也許不是,但我要用一個蘋果,兩個香蕉和一個橙子編輯我的問題。大聲笑 – toddmo 2014-11-01 23:20:44

+0

我印象深刻!非常聰明!我會研究這個,直到我理解它。 – toddmo 2014-11-01 23:22:10

0

這裏的VB版本:

<System.Runtime.CompilerServices.Extension()> 
    Public Function Unique(List As List(Of String)) As List(Of String) 
    ' 1. Remember the initial order 
    ' 2. Group by the text 
    ' 3. Label the entries in each group 
    ' 4. Now reorder them by their original order 
    ' 5. Remove the order value to get back to just the name 
    Return List. 
     Select(Function(Item, Index) New With {Item, Index}). 
     GroupBy(Function(IndexedItem) IndexedItem.Item). 
     SelectMany(Function(Group) Group.Select(Function(GroupItem, GroupIndex) New With {.Index = GroupItem.Index, .UniqueItem = GroupItem.Item & If(GroupIndex = 0, String.Empty, (GroupIndex + 1).ToString)})). 
     OrderBy(Function(IndexedUniqueItem) IndexedUniqueItem.Index). 
     Select(Function(IndexedUniqueItem) IndexedUniqueItem.UniqueItem). 
     ToList() 
    End Function