裁剪字符串数组中的第一个元素,而不将所有元素复制到新数组中
本文关键字:元素 数组 复制 新数组 字符串 第一个 裁剪 | 更新日期: 2023-09-27 18:29:33
有一个字符串数组
string[] lines
我想删除第一个元素。因此,如果数组有5个元素,我希望最终得到4个。
有很多方法可以实现这一点:
创建一个新的字符串数组,其大小与原始数组的大小相同。然后简单地复制所有元素(第一个元素除外)。我不喜欢这样,因为,好吧,你必须制作一个全新的数组,并且似乎重复了内存使用情况(?)
使用像
List
这样的集合来实现此操作的方法。但情况也是如此:我必须将字符串数组转换为列表,然后删除第一个元素,然后将列表转换为字符串数组(因为我需要字符串数组,而不是列表)。System.Array.Resize()
似乎能够"裁剪"数组,这正是我所需要的。然而,它裁剪了"最右边"的元素,而我需要裁剪第一个(最左边)元素。
我的问题是:有没有一种更简单的方法可以消除字符串数组中的第一个元素,最终得到一个大小比原来的小一的数组?
我不知道你想用"裁剪"版本做什么,但一个非常便宜的方法是在ArraySegment<>
中顶部包裹lines
,就像这样:
var cropped = new ArraySegment<string>(lines, 1, 4);
自.NET 4.5(2012年起)以来,ArraySegment<>
实现了一些接口,因此您可以执行以下操作:
foreach (var l in cropped)
{
// ...
}
(在ArraySegment<>
上使用显式接口实现,迭代变量l
是强类型的)。
请记住,这只是原始数组实例的包装器。如果修改了该数组,则会在ArraySegment<>
中反映出来。没有复制(甚至没有一个肤浅的复制)。
如果需要索引等,请将ArraySegment<>
结构的值框为IReadOnlyList<>
或IList<>
:
IReadOnlyList<string> croppedB = new ArraySegment<string>(lines, 1, 4);
或:
IList<string> croppedC = new ArraySegment<string>(lines, 1, 4);
如果你真的喜欢这个整体"不要创建一个新数组",你可以使用startIndex和长度变量,并始终保持整个数组的原样,只通过这两个值将其一部分标记为可用。但是,如果你不喜欢大阵列大小和边缘性能,如果你只创建一个新阵列,你的程序看起来会更干净,更容易理解、创建和维护:
var arrayMinusFirstElement = lines.Skip(1).ToArray()
此解决方案模拟一个数组,您可以在末尾添加项,并从开始裁剪项。无论添加或裁剪了多少项,都可以始终使用基于零的索引器。它是一个队列,您可以修改它的元素并通过它们的索引访问它们。
var lines = new DicAsArray<string>();
lines.Add("zero");
lines.Add("one");
lines.Add("two");
lines.Add("three");
lines.Add("four");
lines.Crop();
lines[2] = "!!!";
for (int i = 0; i < lines.Count; i++)
{
Console.WriteLine(lines[i]);
}
剩下的就像
public class DicAsArray<T>
{
public DicAsArray()
{
_dic = new Dictionary<int, T>();
_minIndex = 0;
_maxIndex = -1;
}
public void Add(T item)
{
_dic[++_maxIndex] = item;
}
public T Crop()
{
_croppedCount++;
var item = _dic[_minIndex];
_dic.Remove(_minIndex++);
return item;
}
public T this[int index]
{
get
{
var mappedIndex = _croppedCount + index;
return _dic[mappedIndex];
}
set
{
var mappedIndex = _croppedCount + index;
if (mappedIndex > _maxIndex || mappedIndex < _minIndex)
throw new IndexOutOfRangeException();
_dic[mappedIndex] = value;
}
}
public int Count { get { return _dic.Count; } }
private Dictionary<int, T> _dic;
private int _maxIndex;
private int _minIndex;
private int _croppedCount;
}
您说Array.Resize()
裁剪最右边的元素,然后简单地先反转数组,然后再反转。
Array.Reverse(Array.Resize(Array.Reverse(myArray)))