2013-07-22 51 views
-3

我想要一個通用的方法來找到第一個位置(我們可以將一個索引當作位置),其中給定的數據比一個大而且小於下一個。C#List <T>是否有擴展的FirstBetween方法?

例如,我有一個int列表[12,34,4,65],如果我給一個數字15(它比12和小於34)大,它應該返回1,如果我給一個數字50它應該返回3等

這是我寫的,但我覺得必須有一個更簡單的方法:

public static class ExtensionMethods 
{ 
    public static int FirstBetween<T>(this List<T> list, T t) 
    { 
     if (list == null) 
      return -1; 
     if(t == null) 
      return -1; 
     if(list.Count == 0) 
      return 0; 

     T item1; 
     for(int index = 0;index<list.Count;index++) 
     { 
      T item2 = list[index]; 
      if(IsBetween(item1,item2,t)) 
       return index; 

      item1 = item2;    
     }   
     return list.Count; 
    } 

    private static bool IsBetween<T>(T t1, T t2, T t) 
    { 
     if (t1 == null && t2 == null) 
      return false; 
     else if(t1==null && t<=t2)//in case of the first item 
      return true; 
     else if (t2 == null && t >= t1)//in case of the last item 
      return true; 
     else if(t>=t1 && t<=t2) 
      return true; 
     else 
      return false; 
    } 
} 

這是未完成的代碼,我覺得這太複雜了,並作爲模板方法它仍然有一些其他問題。

有沒有更簡單的方法來做到這一點?

+0

1)你有什麼試過? 2)看起來很不一致。 –

+2

聽起來不太難,你能告訴我們你試過了什麼嗎? – gdoron

+0

我不得不迭代列表並使用比較來查找結果。我想知道是否有一種簡單的方法來做到這一點。 – Gisway

回答

0
private int? returnIndex(int val = 15) 
     { 
      List<int> myList = new List<int>() { 12, 34, 4, 65 }; 
      int listCount = myList.Count; 
      int? position = null; 
      for (int i = 0; i < listCount; i++) 
      { 
       var currPosition = myList[i]; 
       if (i + 1 >= listCount) 
       { 
        position = i; 
        break; 
       } 
       var nextPosition = myList[i + 1]; 
       if (val >= currPosition && val <= nextPosition) 
       { 
        position = i +1; 
        break; 
       } 
      } 
      return position; 
     } 
+0

這是一個非常奇怪而且沒有優化的代碼。爲什麼你在'for'結尾處有'continue'? –

+0

它應該只是休息,我想念打字。去編輯。 答案只是因爲小姐繼續投票而落選? –

+0

不,我低估了,因爲您爲每個元素訪問數組兩次,並且您的代碼不可讀。 –

3

使用的泛型類型IComparable的約束應該做的伎倆:

public static int FirstBetween<T>(this List<T> list, T value) where T:IComparable<T> { 
     if (list == null || value == null) return -1; 

     for (int index = 1; index < list.Count; index++) { 
      if ((list[index - 1].CompareTo(value) < 0) 
        && list[index].CompareTo(value) > 0) 
       return index; 
     } 
     return list.Count; 
    } 

優化的版本,但可讀性變差,還沒有檢查列表空項,是什麼讓事情變得醜陋:

public static int FirstBetween<T>(this List<T> list, T value) where T:IComparable<T> { 
     if (list == null && value == null) return -1; 
     if (list.Count == 0) return 0; 
     var last = value.CompareTo(list[0]); 
     for (int index = 1; index < list.Count; index++) { 
      if ((last > 0) && (last = value.CompareTo(list[index])) < 0) 
       return index; 
     } 
     return list.Count; 
    } 
+0

+1我認爲就是這樣,至少是這個想法。可以對此代碼進行優化,以避免兩次比較每個數組項的「值」。還有一個人應該小心一些列表項可能爲空,所以你最好反過來進行比較:'value.CompareTo(list [index])'。 – jods

+0

@jods你是對的,但優化是邪惡的:P我認爲,比較兩次無法避免,因爲列表沒有排序... – Blau

+0

@Blau *早熟*優化是所有邪惡的根源,俗話說得好。這並不是說所有的優化都是邪惡的。還要注意列出的幾條評論是優化正確性,而不是速度。添加代碼來處理像空值這樣的事情很重要,而且絕對不是邪惡的。 – Servy

0
public static int? FirstBetween<T>(this List<T> list, T val) where T : IComparable 
    { 
     if (list != null && !ReferenceEquals(val, null)) 
     { 
      bool greater = false; 
      for (int i = 1; i < list.Count; i++) 
      { 
       var lastGreater = i == 1 ? (list[i-1].CompareTo(val) > 0) : greater; 
       greater = list[i].CompareTo(val) > 0; 
       if (!lastGreater && greater) 
        return i; 
      } 
     } 
     return null; 
    }