2011-10-19 42 views
0

我有客戶Ids[customerIdsList]的C#泛型列表集合.Lets說,它的計數是25處理收集成套

我需要在臺10的值,這將是配置和讀取通過這些ID app.config] 到另一個方法ProcessCustomerIds(),它將逐個處理這個客戶。 即。第一次迭代將通過10,接下來會通過下一個10個用戶ID並且最後一個將通過5個IAD ...等等等等等等...

如何使用Linq實現此目的? 我可以使用Math.DivRem來做到這一點嗎?

int result=0; 
int quotient = Math.DivRem(customerIdsList.Count, 10, out result) 
Output: 
quotient=2 
result=5 

所以,我將迭代customerIdsList 2次,並在每一步調用ProcessCustomerIds()

如果結果值大於0,則我將執行customerIdsList.Skip(25結果)以獲取集合中的最後5個customerIds。 有沒有其他更清潔,更有效的方法來做到這一點?請指教。

+0

爲什麼?什麼做10塊(或N)的塊給你? – Enigmativity

+0

ProcessCustomerIds()是在第三方服務器上通過http進行的調用,並且通常非常流程密集型。因此,我希望以塊爲單位進行處理,而不是爲每個客戶ID創建新的調用。 – user74042

+0

我仍然沒有看到好處。如果您以塊的形式調用服務器,則仍然在處理所有元素。如果你一個接一個地處理數據塊,或者一次全部處理,服務器就會變得很忙。還是你試圖更快地將結果返回給用戶? – Enigmativity

回答

3

在我們的項目中,我們有一個擴展方法「Slice」,它完全符合你的要求。它看起來像這樣:

public static IEnumerable<IEnumerable<T>> Slice<T>(this IEnumerable<T> list, int size) 
{ 
    var slice = new List<T>(); 
    foreach (T item in list) 
    { 
     slice.Add(item); 
     if (slice.Count >= size) 
     { 
      yield return slice; 
      slice = new List<T>(); 
     } 
    } 

    if (slice.Count > 0) yield return slice; 
} 

你使用這樣的:

customerIdsList.Slice(10).ToList().ForEach(ProcessCustomerIds); 

這個實現的一個重要特點是它支持延遲執行。 (與使用GroupBy的方法相反)。誠然,這在大多數情況下並不重要,但有時候確實如此。

1

是的,您可以使用SkipTake方法。

例如:

List <MyObject> list = ...; 
int pageSize = 10; 
int pageNumber = list.Count/pageSize; 
for (int i =0; i<pageNumber; i++){ 
    int currentItem = i * pageSize; 
    var query = (from obj in list orderby obj.Id).Skip(currentItem).Take(pageSize); 
    // call method 
} 

記住要對列表進行排序,如果你想使用SkipTake

+0

只有當集合實現「IList 」時,這才能很好地工作。如果不是,它會一遍又一遍迭代集合,導致O(N^2)時間複雜度。對於一些集合,你不能遍歷它們多次。 – svick

3

你總是可以使用這個組的集合:

var n = 10; 
var groups = customerIdsList 
    .Select((id, index) => new { id, index = index/n }) 
    .GroupBy(x => x.index); 

然後,只需通過團體管理,並在同一時間發出該組的服務器一組的成員。

+0

+1用於使用現有的擴展方法,而不是像對待特定場景一樣爲自己的自定義行爲做夢。 –

+0

+1,這是一個非常有用的技巧,但並不廣爲人知。 – Jon

+0

我不喜歡這個解決方案(而不是Geert的),它總是將整個集合複製到一個臨時哈希表中。這意味着它會使用不必要的太多內存,並且它無法用於無限收集。當然,這些事情並不總是很重要。 – svick

0

一個簡單的擴展:

public static class Extensions 
{ 
    public static IEnumerable<IEnumerable<T>> Chunks<T>(this List<T> source, int size) 
    { 
     for (int i = 0; i < source.Count; i += size) 
     { 
      yield return i - source.Count > size 
          ? source.Skip(i) 
          : source.Skip(i).Take(size); 
     } 
    } 
} 

,然後用它喜歡:

var chunks = customerIdsList.Chunks(10); 

foreach(var c in chunks) 
{ 
    ProcessCustomerIds(c); 
}