我正在尝试使用 C# 将数组中的多个元素移动到末尾。
我有一个数组(在我的例子中是一个字符数组)和一个整数 z
。现在我想将 z
个字符移到另一个数组的末尾,其他字符应该移到数组的开头。
因此,如果第一个数组是 {'H','E','L','L','O'}
和 z = 3
,则新数组应该是 {'L','O','H','E','L'}
。
我希望有人能帮助我。
最佳尝试:
static char[] rotate(char[] c, int z)
{
char[] nc = new char[c.Length];
for (int i = z; i < c.Length; i++)
{
nc[i - z] = c[i];
}
for (int i = 0; i < z; i++)
{
nc[i + z] = c[i];
}
return nc;
}
答案 0 :(得分:1)
只需使用 Array.Copy
将一个 Array 中的一系列元素复制到另一个 Array 并执行 根据需要键入转换和装箱。
public static void DoStuff<T>(T[]source, int z)
{
var start = source[0..z];
Array.Copy(source, z, source, 0, source.Length - z);
Array.Copy(start, 0, source, source.Length - z, z);
}
测试
var chars = "asdfghjk".ToCharArray();
DoStuff(chars, 3);
Console.WriteLine(string.Join(", ", chars));
迭代器的另一种方式
public static IEnumerable<T> DoStuff<T>(T[]source, int z)
=> source.Select((t, i) => source[(i + z) % source.Length]);
或者使用 for 循环
public static T[] DoStuff<T>(T[]source, int z)
{
var result = new T[source.Length];
for (int i = 0; i < source.Length; i++)
result[i] = source[(i + z) % source.Length];
return result;
}
超级高效的零分配
public static unsafe void DoStuff(char[] source, int z)
{
var start = stackalloc char[source.Length];
fixed (char* pArray = source)
{
Buffer.MemoryCopy(pArray, start, z*sizeof(char), z * sizeof(char));
Buffer.MemoryCopy(pArray+z, pArray, (source.Length-z)*sizeof(char) , (source.Length - z) * sizeof(char));
Buffer.MemoryCopy(start, pArray+ (source.Length - z), z * sizeof(char), z * sizeof(char));
}
}
输出
f, g, h, j, k, a, s, d
注意:这缺少合适的输入验证和范围检查,以及一个描述性名称。我会把它留给你
答案 1 :(得分:1)
问题在于您代码中的错误索引。
这是固定版本:
static char[] rotate(char[] c, int z)
{
char[] nc = new char[c.Length];
for (int i = z; i < c.Length; i++)
{
nc[i - z] = c[i];
}
for (int i = 0; i < z; i++)
{
nc[i + z - 1] = c[i]; // <-- Change here
}
return nc;
}
然而,更好的解决方案可能是使用 doubly-linked lists 来更好地处理数组项的移动以开始/结束。双向链表的 .NET 实现是 LinkedList Class。 here 你可以找到一些例子来说明如何做到这一点。
答案 2 :(得分:0)
您可以在一行中使用 LINQ 而无需像这样处理数组:
using System.Linq;
var letters = new[] { 'H', 'E', 'L', 'L', 'O' };
int posToRotate = 3;
var lettersRotated = letters.Skip(posToRotate).Concat(letters.Take(posToRotate)).ToArray();
Console.WriteLine(new string(lettersRotated));
假设 letters
已分配且不为空。
如果位置超过长度,则什么都不做,但可以先检查以避免处理(也可以检查负索引)。
我们skip前N个字符(取其余),然后我们add我们take的前N个字符。
我们调用 ToArray 是因为 LINQ 适用于 IEnumerable<>(和 IQueryable<>),所以执行是 deferred 直到这里。
要替换原来的数组,只需写:
letters = letters.Skip(posToRotate).Concat(letters.Take(posToRotate)).ToArray();
输出
LOHEL