2011-07-09 66 views
1

沒關係,我有類對象的列表,像這樣: 從包含列表可能重複獲取特定項目的索引

List<fruit> lst = new List<fruit>(); 
    lst.Add(orange); 
    lst.Add(apple); 
    lst.Add(grape); 
    lst.Add(grape); 
    lst.Add(orange); 
    lst.Add(pear); 
    lst.Add(apple);

我希望能夠問列表類似 GetIndex(「橙色」 ,2)並讓它返回(在這種情況下)所討論對象的第二個實例(位置4)的索引號。

此列表將被動態填充,甚至可能沒有橙色開頭。如果是這樣,我想要第二個參數的實例號。所以我可以得到第二個橙子,或得到第五個芒果等。

list.IndexOf(orange)返回任何重複的第一個實例,所以我需要別的東西。

任何想法? PS:我沒有提到第一個參數將是一個字符串!

+1

你的意思'GetIndex(橙色,2)'? – svick

+0

@Neith,你是否總是想要重複的位置,如果它有三個項目會發生什麼 – kobe

+0

@Neith爲什麼不字典並將它們存儲爲唯一值並稍後查詢並找到所需的元素。 – kobe

回答

1

你可以用自己的方法擴展類爲類,不幸的是這是不可能的泛型類,所以相反,你給這種方法的類型。

public static class ListExtension 
{ 
    public static int GetIndex<T>(this List<T> list, T value, int skipMatches = 1) 
    { 
     for (int i = 0; i < list.Count; i++) 
      if (list[i].Equals(value)) 
      { 
       skipMatches--; 
       if (skipMatches == 0) 
        return i; 
      } 
     return -1; 
    } 
} 

List<int> list = new List<int>(); 
list.Add(3); 
list.Add(4); 
list.Add(5); 
list.Add(4); 
int secondFour = (int)list.GetIndex(4, 2); 
+0

這幾乎是完美的,但我需要能夠以字符串形式獲取對象(請參閱編輯的OP)。 – Neith

+0

nvm,我重新爲它做了我需要的!感謝大家! – Neith

2
 int index = lst.IndexOf(orange); 
     if (index >= 0) 
     { 
      index = lst.IndexOf(orange, index + 1); 
     } 

或使其通用的,可以用一些LINQ:

static int GetIndex(IEnumerable<Fruit> li, Fruit ob, int k) 
    { 
     var tmp = li.Select((it, i) => new Tuple<int, Fruit>(i, it)).Where(tup => tup.Item2 == ob).Skip(k - 1).FirstOrDefault(); 
     if (tmp == null) 
      return -1; 
     else 
      return tmp.Item1; 
    } 

然後調用GetIndex(lst, orange, 2)

+0

如果他有3次橙色,它總是會給第二個位置,OP會總是隻有兩個重複,這會發生什麼? – kobe

+0

@kobe:這很容易擴展(用循環)來找到* n * th的副本。 –

+0

@ben,thats kool – kobe

1
var result = list.Select((x, i) => new { x, i }) 
        .Where(t => t.x == fruit) 
        .Skip(k - 1) 
        .Select(t => t.i) 
        .First(); 
+0

這比看起來效率更高,只要在沒有足夠的匹配時出現異常就是期望的結果。 –

+0

如果你可以用'ElementAt()'更清楚地調用'Skip()'然後'First()',爲什麼要調用? – svick

+0

@svick:我只是稍微修改了@BrokenGlass的答案(它使用了Skip和FirstOrDefault),並將解決方案與ElementAt一起發佈(並接收代表);-) – dtb

2

這裏有一個通用的擴展搜索我只寫了:

public static class ListExtension 
{ 
    public static int GetIndex<T>(this List<T> entity, T what, int find) 
    { 
     int found = 0; 
     int index = -1; 

     while ((index = entity.IndexOf(what, (index + 1))) != -1) 
     { 
      found++; 

      if (found == find) 
       break; 
     } 

     return (index); 
    } 
} 

你所要做的就是叫它像這樣:

int index = lst.GetIndex(apple, 2); 

如果找不到的項目,它返回-1。

+0

int index = -1; ? – dtb

+0

按照預期:找不到第二個'T'(或蘋果),所以它返回-1。 –

+1

我的意思是,如果find == 1,並且實體的第一個出現在索引== 0,那麼您的方法不會找到它,因爲您在索引1處開始搜索。所以我建議將索引的初始化從0爲-1。除非我錯了...... – dtb

3
public static int GetIndex<T>(this IEnumerable<T> lst, T obj, int index) 
{ 
    return lst.Select((o, i) => new { o, i }) 
       .Where(x => x.o.Equals(obj)) 
       .ElementAt(index - 1) 
       .i; 
} 

雖然這是一種奇怪的是index從1開始,但結果從0開始

0

當你沒有找到你要找的價值DTB的答案賬戶的擴展:

public int GetIndex<T>(IEnumerable<T> list, T item, int itemNum) { 
    // result is a nullable int containing the index 
    var result = list.Select((x, i) => new { x, i }) 
        .Where(t => item.Equals(t.x)) 
        .Skip(itemNum - 1) 
        .Select(t => (int?)t.i) 
        .FirstOrDefault(); 
    // return -1 when item was not found 
    return (result.HasValue ? result.Value : -1); 
} 
相關問題