如何在C#中移动数组的开头?
我正在尝试根据第一次出现的值重新组织一个数组(从而模拟与圆形数组类似的function。)
例如,在下面的数组中,我希望第一次出现的值6成为新的第一个元素,而先前的元素成为后者:
所以:
int[] myArray = {2, 3, 6, 1, 7, 6};
变为:
myArray = {6, 1, 7, 6, 2, 3};
实现这一目标的“最佳”方式是什么?
int[] myArray = { 2, 3, 6, 1, 7, 6 }; myArray = myArray .SkipWhile(i => i != 6) .Concat(myArray.TakeWhile(i => i != 6)) .ToArray();
应该做的伎俩!
您需要使用System.Linq
;
Thorsten的解决方案创建了一个新arrays; 这是一个就地版本,它只创建一个与旋转大小一样大的临时数组:
public static void RotateLeft(T[] array, int places) { T[] temp = new T[places]; Array.Copy(array, 0, temp, 0, places); Array.Copy(array, places, array, 0, array.Length - places); Array.Copy(temp, 0, array, array.Length - places, places); }
我确信它可以只用一个临时缓冲项来完成,但它会更复杂:)
作为一种效率衡量标准,这里是一个“向左旋转一个地方”的快捷方式:
public static void RotateLeft(T[] array) { T temp = array[0]; Array.Copy(array, 0, array, 1, array.Length - 1); array[array.Length-1] = temp; }
您可以执行以下操作:
- 创建与原始大小相同的新数组
- 确定您的“开始索引”
- 使用
Array.Copy()
将从开始索引到源数组末尾的所有内容复制到目标数组 - 使用
Array.Copy()
复制从0开始到源数组的索引到目标数组末尾的所有内容
这样,您就可以得到您所期望的源数组副本。
但是,你必须使用Array.Copy()
各种重载,因为我现在不知道确切的参数值。
首先,进行线性搜索以查找要创建第一个元素的值的第一个匹配项:
// value contains the value to find. int skip; for (int i = 0; i < array.Length; i++) { if (array[i] == value) { skip = i; break; } } // skip contains the index of the element to put at the front. // Equivalently, it is the number of items to skip. // (I chose this name for it because it makes the subtractions // in the Array.Copy implementation more intuitive.)
你想改变实际的arrays吗? 然后做Thorsten Dittmar建议的事情:
int[] array = new int[] { 2, 3, 6, 1, 7, 6 }; int[] result = new int[array.Length]; int skip = 2; // So that array[skip] will be result[0] at the end Array.Copy(array, skip, result, 0, array.Length - skip); Array.Copy(array, 0, result, array.Length - skip, skip);
您是否只想以新的顺序查看数组,而不做其他任何事情? 然后将其编入索引:
array[(i + skip) % array.Length] // Instead of array[i]
编辑:只是为了笑,Jon Skeet建议在仅使用单个缓冲区值( sourceValue
)的情况下实现副本:
// GCD gives the greatest common divisor int gcd = GCD(array.Length, skip); // period is the length of the permutation cycles in our rotation. int period = array.Length / gcd; int max = array.Length / period; for (int i = 0; i < max; i++) { int sourceIndex = i; int sourceValue = array[sourceIndex]; for (int n = 1; n <= period; n++) { int destinationIndex = (sourceIndex + array.Length - skip) % array.Length; int temp = array[destinationIndex]; array[destinationIndex] = sourceValue; sourceValue = temp; sourceIndex = destinationIndex; } }
作为创建新数组的替代方法,您可以使用类包装它:
class CircularList : IList { static IEnumerable ToEnumerator(CircularList list) { for (int i = 0; i < list.Count; i++) { yield return list[i]; } } IList arr; public int Shift { get; private set; } public CircularList(IList arr, int shift) { this.arr = arr; this.Shift = shift; } int shiftIndex(int baseIndex) { return (baseIndex + Shift) % arr.Count; } #region IList Members public int IndexOf(T item) { throw new NotImplementedException(); } public void Insert(int index, T item) { throw new NotImplementedException(); } public void RemoveAt(int index) { throw new NotImplementedException(); } public T this[int index] { get { return arr[shiftIndex(index)]; } set { arr[shiftIndex(index)] = value; } } #endregion #region ICollection Members public void Add(T item) { throw new NotImplementedException(); } public void Clear() { throw new NotImplementedException(); } public bool Contains(T item) { throw new NotImplementedException(); } public void CopyTo(T[] array, int arrayIndex) { throw new NotImplementedException(); } public int Count { get { return arr.Count; } } public bool IsReadOnly { get { throw new NotImplementedException(); } } public bool Remove(T item) { throw new NotImplementedException(); } #endregion #region IEnumerable Members public IEnumerator GetEnumerator() { return ToEnumerator(this).GetEnumerator(); } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ToEnumerator(this).GetEnumerator(); } #endregion }
这个程序:
class Program { static void Main(string[] args) { int[] myArray = { 2, 3, 6, 1, 7, 6 }; CircularList circularList = new CircularList (myArray, Array.IndexOf (myArray, 6)); foreach (int i in circularList) { Console.WriteLine(i); } } }
打印以下内容:
6 1 7 6 2 3
var ar = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; ar = ar.SkipWhile(a => a != 6).ToArray();
C#回答:输入:{1,2,3,5,6,7,8}; 输出:{8,7 1,2,3,5,6};
{ static void Main(string[] args) { int[] array = { 1, 2, 3, 5, 6, 7, 8 }; int index = 2; int[] tempArray = new int[array.Length]; array.CopyTo(tempArray, 0); for (int i = 0; i < array.Length - index; i++) { array[index + i] = tempArray[i]; } for (int i = 0; i < index; i++) { array[i] = tempArray[array.Length -1 - i]; } } }
新方法仅适用于.NET 4.5(2012年起)或更高版本:
const int value = 6; int[] myArray = { 2, 3, 6, 1, 7, 6, }; var index = Array.IndexOf(myArray, value); if (index == -1) throw new InvalidOperationException(); var rotatedArray = (new ArraySegment(myArray, index, myArray.Length - index)) .Concat(new ArraySegment (myArray, 0, index)) .ToArray();
在早期的.NET版本中, ArraySegment<>
值不能用作IEnumerable<>
。
我不清楚是否需要对原始数组实例进行变异,但如果需要,只需附加:
rotatedArray.CopyTo(myArray, 0);
到我的代码。
上述就是C#学习教程:如何在C#中移动数组的开头?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1012104.html