2013-08-06 57 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]'间隔大小。 –

相关问题