将列表中的元素作为第一个元素的最快方法

时间:2013-08-06 06:40:31

标签: c# list

我有列表,我想要一个简短而快速的方法,将其中一个元素作为第一个。 我想到使用下面的代码来选择第10个元素并将其作为第一个元素。但寻找更好的解决方案

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

2 个答案:

答案 0 :(得分:3)

如果你不介意其余部分的排序,你实际上可以在0和10位置交换两个项目,相信它比插入和删除更好:

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

你甚至可以将它作为List的扩展,以便于使用,例如:

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

答案 1 :(得分:0)

在某些特殊情况下,您可以获得更好的性能(为了简单起见,我假设值总是在取自它的位置之前插入):

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之间的差距较小,您将获得更好的结果。随着此间隔增加,性能将下降。我想你可能想要评估这个差距并根据它的价值采取最佳分支。