Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在c中旋转列表的最简单方法#_C#_Arrays_Linq_List - Fatal编程技术网

C# 在c中旋转列表的最简单方法#

C# 在c中旋转列表的最简单方法#,c#,arrays,linq,list,C#,Arrays,Linq,List,列表显示我有一个列表list{1,2,3,4,5} 旋转是指: => {2,3,4,5,1} => {3,4,5,1,2} => {4,5,1,2,3} 也许“旋转”不是最好的词,但希望你明白我的意思 我的问题是,什么是最简单的方法(简而言之,c#4 Linq就绪),并且不会受到性能(合理性能)的影响 谢谢。 最简单的方法(对于列表)是使用: int first = list[0]; list.RemoveAt(0); list.Add(first); 但是性能很差-O(n

列表显示我有一个列表
list{1,2,3,4,5}

旋转是指:

=> {2,3,4,5,1} => {3,4,5,1,2} => {4,5,1,2,3}
也许“旋转”不是最好的词,但希望你明白我的意思

我的问题是,什么是最简单的方法(简而言之,c#4 Linq就绪),并且不会受到性能(合理性能)的影响

谢谢。

最简单的方法(对于
列表
)是使用:

int first = list[0];
list.RemoveAt(0);
list.Add(first);
但是性能很差-O(n)

阵列

这基本上等同于
列表
版本,但更为手动:

int first = array[0];
Array.Copy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = first;

如果您可以使用
链接列表
,则会简单得多:

int first = linkedList.First;
linkedList.RemoveFirst();
linkedList.AddLast(first);
这是O(1),因为每个操作都是恒定时间

cadrell0使用队列的解决方案是一条语句,因为
Dequeue
删除元素并返回它:

queue.Enqueue(queue.Dequeue());
虽然我找不到任何关于此性能特征的文档,但我希望使用数组和索引作为“虚拟起点”来实现
Queue
——在这种情况下,这是另一个O(1)解决方案

请注意,在所有这些情况下,您都希望首先检查列表是否为空。(你可以认为这是一个错误,或者是一个不可操作的问题。)

试试看

List<int> nums = new List<int> {1,2,3,4,5};
var newNums = nums.Skip(1).Take(nums.Count() - 1).ToList();
newNums.Add(nums[0]);
List nums=新列表{1,2,3,4,5};
var newNums=nums.Skip(1).Take(nums.Count()-1).ToList();
newNums.Add(nums[0]);
不过,我更喜欢Jon Skeet的答案。

这个怎么样:

var output = input.Skip(rot)
                  .Take(input.Count - rot)
                  .Concat(input.Take(rot))
                  .ToList();
其中
rot
是要旋转的点的数量-必须小于
input
列表中的元素数量


正如@cadrell0 answer所示,如果这是您对列表所做的全部操作,那么您应该使用队列而不是列表。

您可以将其实现为队列。出队列和入队列的值相同


**我不确定将列表转换为队列的性能,但人们对我的评论投了更高的票,所以我将此作为答案发布。

似乎一些回答者将此视为探索数据结构的机会。虽然这些答案信息丰富且有用,但它们并不十分简单

Linq'ish方法是:得到一个扩展方法,该方法返回一个懒惰的IEnumerable,它知道如何构建所需的内容。此方法不修改源,仅应在必要时分配源的副本

public static IEnumerable<IEnumerable<T>> Rotate<T>(this List<T> source)
{
  for(int i = 0; i < source.Count; i++)
  {
    yield return source.TakeFrom(i).Concat(source.TakeUntil(i));
  }
}

  //similar to list.Skip(i-1), but using list's indexer access to reduce iterations
public static IEnumerable<T> TakeFrom<T>(this List<T> source, int index)
{
  for(int i = index; i < source.Count; i++)
  {
    yield return source[i];
  }
}

  //similar to list.Take(i), but using list's indexer access to reduce iterations    
public static IEnumerable<T> TakeUntil<T>(this List<T> source, int index)
{
  for(int i = 0; i < index; i++)
  {
    yield return source[i];
  }
}
public static IEnumerable Rotate(此列表源代码)
{
for(int i=0;i
用作:

List<int> myList = new List<int>(){1, 2, 3, 4, 5};
foreach(IEnumerable<int> rotation in myList.Rotate())
{
  //do something with that rotation
}
List myList=newlist(){1,2,3,4,5};
foreach(myList.Rotate()中的IEnumerable rotation)
{
//用这个旋转做点什么
}

您可以在.net framework中玩得很好

我知道你想要做的更多的是一个迭代行为,而不是一个新的集合类型;因此,我建议您尝试这种基于IEnumerable的扩展方法,它将用于集合、列表等

class Program
{
    static void Main(string[] args)
    {
        int[] numbers = { 1, 2, 3, 4, 5, 6, 7 };

        IEnumerable<int> circularNumbers = numbers.AsCircular();

        IEnumerable<int> firstFourNumbers = circularNumbers
            .Take(4); // 1 2 3 4

        IEnumerable<int> nextSevenNumbersfromfourth = circularNumbers
            .Skip(4).Take(7); // 4 5 6 7 1 2 3 
    }
}

public static class CircularEnumerable
{
    public static IEnumerable<T> AsCircular<T>(this IEnumerable<T> source)
    {
        if (source == null)
            yield break; // be a gentleman

        IEnumerator<T> enumerator = source.GetEnumerator();

        iterateAllAndBackToStart:
        while (enumerator.MoveNext()) 
            yield return enumerator.Current;

        enumerator.Reset();
        if(!enumerator.MoveNext())
            yield break;
        else
            yield return enumerator.Current;
goto iterateAllAndBackToStart;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
int[]数字={1,2,3,4,5,6,7};
IEnumerable circular numbers=numbers.AsCircular();
IEnumerable FirstFourNumber=循环数
.拿(4);/1234
IEnumerable nextSevenNumbersfromfourth=循环数
.跳过(4).拿(7);//4 5 6 7 1 2 3
}
}
公共静态类循环数
{
公共静态IEnumerable AsCircular(此IEnumerable源)
{
if(source==null)
让步;做一个绅士
IEnumerator枚举器=source.GetEnumerator();
iterateAllAndBackToStart:
while(枚举数.MoveNext())
产生返回枚举数。当前;
枚举数。重置();
如果(!enumerator.MoveNext())
屈服断裂;
其他的
产生返回枚举数。当前;
转到iterateAllAndBackToStart;
}
}
  • 合理性能
  • 灵活的
如果您想更进一步,请制作一个
循环列表
,并按住相同的枚举数,以便在像示例中那样旋转时跳过
skip()

我使用这个:

public static List<T> Rotate<T>(this List<T> list, int offset)
{
    return list.Skip(offset).Concat(list.Take(offset)).ToList();
}
公共静态列表旋转(此列表,整数偏移)
{
return list.Skip(offset).Concat(list.Take(offset)).ToList();
}

我的阵列解决方案:

    public static void ArrayRotate(Array data, int index)
    {
        if (index > data.Length)
            throw new ArgumentException("Invalid index");
        else if (index == data.Length || index == 0)
            return;

        var copy = (Array)data.Clone();

        int part1Length = data.Length - index;

        //Part1
        Array.Copy(copy, 0, data, index, part1Length);
        //Part2
        Array.Copy(copy, part1Length, data, 0, index);
    }

我被要求以最小的内存使用率反转字符数组

char[]charArray=new char[]{'C','o','w','b','o','y'}

方法:

static void Reverse(ref char[] s)
{
    for (int i=0; i < (s.Length-i); i++)
    {
        char leftMost = s[i];
        char rightMost = s[s.Length - i - 1];

        s[i] = rightMost;
        s[s.Length - i - 1] = leftMost;
    }
}
静态无效反转(ref char[]s)
{
对于(int i=0;i<(s.Length-i);i++)
{
最左边的字符=s[i];
最右边的字符=s[s.Length-i-1];
s[i]=最右边;
s[s.Length-i-1]=最左边;
}
}

我为此使用了以下扩展:

static class Extensions
{
    public static IEnumerable<T> RotateLeft<T>(this IEnumerable<T> e, int n) =>
        n >= 0 ? e.Skip(n).Concat(e.Take(n)) : e.RotateRight(-n);

    public static IEnumerable<T> RotateRight<T>(this IEnumerable<T> e, int n) =>
        e.Reverse().RotateLeft(n).Reverse();
}

使用模运算如何:

public void UsingModularArithmetic()
{ 
  string[] tokens_n = Console.ReadLine().Split(' ');
  int n = Convert.ToInt32(tokens_n[0]);
  int k = Convert.ToInt32(tokens_n[1]);
  int[] a = new int[n];

  for(int i = 0; i < n; i++)
  {
    int newLocation = (i + (n - k)) % n;
    a[newLocation] = Convert.ToInt32(Console.ReadLine());
  }

  foreach (int i in a)
    Console.Write("{0} ", i);
}
使用ModuleArrithmetic()公开作废
{ 
string[]tokens\u n=Console.ReadLine().Split(“”);
int n=Convert.ToInt32(令牌n[0]);
int k=转换为32(令牌[1]);
int[]a=新的int[n];
对于(int i=0;i

所以,基本上,当我从控制台读取时,将值添加到数组中

我的解决方案可能太基本了(我不想说它是蹩脚的…),而不是林肯式的。
然而,它有一个相当好的性能

int max = 5; //the fixed size of your array.
int[] inArray = new int[5] {0,0,0,0,0}; //initial values only.

void putValueToArray(int thisData)
{
  //let's do the magic here...
  Array.Copy(inArray, 1, inArray, 0, max-1);
  inArray[max-1] = thisData;
}

您可以使用下面的代码进行左旋转

List<int> backUpArray = array.ToList();

for (int i = 0; i < array.Length; i++)
{
    int newLocation = (i + (array.Length - rotationNumber)) % n;
    array[newLocation] = backUpArray[i];
}
List backUpArray=array.ToList();
用于(int i)
List<int> backUpArray = array.ToList();

for (int i = 0; i < array.Length; i++)
{
    int newLocation = (i + (array.Length - rotationNumber)) % n;
    array[newLocation] = backUpArray[i];
}
public static int[] RotationOfArray(int[] A, int k)
  {
      if (A == null || A.Length==0)
          return null;
      int[] result =new int[A.Length];
      int arrayLength=A.Length;
      int moveBy = k % arrayLength;
      for (int i = 0; i < arrayLength; i++)
      {
          int tmp = i + moveBy;
          if (tmp > arrayLength-1)
          {
              tmp =  + (tmp - arrayLength);
          }
          result[tmp] = A[i];             
      }        
      return result;
  }
public static int[] RightShiftRotation(int[] a, int times) {
  int[] demo = new int[a.Length];
  int d = times,i=0;
  while(d>0) {
    demo[d-1] = a[a.Length - 1 - i]; d = d - 1; i = i + 1;
  }
  for(int j=a.Length-1-times;j>=0;j--) { demo[j + times] = a[j]; }
  return demo;
}
List<int> temp = new List<int>();     

 public int[] solution(int[] array, int range)
    {
        int tempLength = array.Length - range;

        temp = array.Skip(tempLength).ToList();

        temp.AddRange(array.Take(array.Length - range).ToList());

        return temp.ToArray();
    }