2013-08-06 55 views
2

我有一個列表,我想要一個簡短而快速的方法來使其元素之一成爲第一個元素。 我想要使用下面的代碼來選擇第10個元素並使其成爲第一個元素。但是,尋找更好的SOLN使列表中的元素成爲第一個元素的最快方法

tempList.Insert(0, tempList[10]); 
tempList.RemoveAt(11); 
+7

你期望得到多快?.. – Sayse

+2

你的解決方案似乎不是很糟糕。 – algreat

+0

我想確保在C#中不存在這樣的代碼,以便避免重複的代碼。 – electricalbah

回答

3

,如果你不介意的話,其餘的排序,你實際上可以在0位和10交換兩個項目,認爲它比做插入和刪除更好:

var other = tempList[0]; 
tempList[0]=tempList[10]; 
tempList[10] = other; 

,你甚至可以使這個名單的,易於使用的延伸,是這樣的:

public static void Swap<T>(this List<T> list, int oldIndex, int newIndex) 
{ 
     // place the swap code here 
} 
+0

他不想交換。他想將第n個元素移動到列表 – Jehof

+4

中的第一個位置(前面),他的問題並不明確 - 他說他想將第n個元素作爲第一個元素,但並未說明他是否想要保留休息...我理解正確嗎?對不起,如果是錯誤的 - 英語不是我的母語:) – Rex

0

還有一些特殊情況下,當你可以得到更好的性能(SIMPL着想孵化城,我假設值,其中它是從所採取的位置之前總是插入):

class Program 
{ 
    const int Loops = 10000; 
    const int TakeLoops = 10; 
    const int ItemsCount = 100000; 
    const int Multiplier = 500; 
    const int InsertAt = 0; 

    static void Main(string[] args) 
    { 
     var tempList = new List<int>(); 
     var tempDict = new Dictionary<int, int>(); 
     for (int i = 0; i < ItemsCount; i++) 
     { 
      tempList.Add(i); 
      tempDict.Add(i, i); 
     } 

     var limit = 0; 
     Stopwatch 
      sG = new Stopwatch(), 
      s1 = new Stopwatch(), 
      s2 = new Stopwatch(); 
     TimeSpan 
      t1 = new TimeSpan(), 
      t2 = new TimeSpan(); 

     for (int k = 0; k < TakeLoops; k++) 
     { 
      var takeFrom = k * Multiplier + InsertAt; 
      s1.Restart(); 
      for (int i = 0; i < Loops; i++) 
      { 
       tempList.Insert(InsertAt, tempList[takeFrom]); 
       tempList.RemoveAt(takeFrom + 1); 
      } 
      s1.Stop(); 
      t1 += s1.Elapsed; 
      s2.Restart(); 
      for (int i = 0; i < Loops; i++) 
      { 
       var e = tempDict[takeFrom]; 
       for (int j = takeFrom - InsertAt; j > InsertAt; j--) 
       { 
        tempDict[InsertAt + j] = tempDict[InsertAt + j - 1]; 
       } 
       tempDict[InsertAt] = e; 
      } 
      s2.Stop(); 
      t2 += s2.Elapsed; 
      if (s2.Elapsed > s1.Elapsed || limit == 0) 
       limit = takeFrom; 
     } 

     sG.Start(); 
     for (int k = 0; k < TakeLoops; k++) 
     { 
      var takeFrom = k * Multiplier + InsertAt; 
      if (takeFrom >= limit) 
      { 
       for (int i = 0; i < Loops; i++) 
       { 
        tempList.Insert(InsertAt, tempList[takeFrom]); 
        tempList.RemoveAt(takeFrom + 1); 
       } 
      } 
      else 
      { 
       for (int i = 0; i < Loops; i++) 
       { 
        var e = tempDict[takeFrom]; 
        for (int j = takeFrom - InsertAt; j > InsertAt; j--) 
        { 
         tempDict[InsertAt + j] = tempDict[InsertAt + j - 1]; 
        } 
        tempDict[InsertAt] = e; 
       } 
      } 
     } 
     sG.Stop(); 
     Console.WriteLine("List:  {0}", t1); 
     Console.WriteLine("Dictionary: {0}", t2); 
     Console.WriteLine("Optimized: {0}", sG.Elapsed); 

     /*************************** 
     List:  00:00:11.9061505 
     Dictionary: 00:00:08.9502043 
     Optimized: 00:00:08.2504321 
     ****************************/ 
    } 
} 

在上面的例子,一個Dictionary<int,int>被用來存儲每個元素的索引。如果insertAttakeFrom之間的差距較小,您將獲得更好的結果。隨着間隔的增加,性能會下降。我想你可能想要評估這個差距,並根據它的價值來選擇最佳分支。

+0

爲什麼不''var e = tempDict [10];'?除此之外:我不敢相信這比以某種方式使用插入/刪除更快。這些方法在內部複製了運行時通常很好支持的數組。 – oddparity

+0

你是對的,已更新。測試表明,它的速度更快一些'[insertAt,takeFrom]'間隔大小。 –

相關問題