gpt4 book ai didi

c# - ArraySegment - 返回实际段 C#

转载 作者:可可西里 更新时间:2023-11-01 07:45:44 26 4
gpt4 key购买 nike

我一直在寻找方法来返回基本上由 ArraySegment 在偏移量和计数方面持有的段。尽管 ArraySegment 拥有完整的原始数组,但它只是将其分隔,因为对段的任何更改都会反射(reflect)到原始数组中。问题或者说 ArraySegment 的局限性是它不会将段本身作为一个整体返回,我必须遍历这些值。返回整个分割市场的最佳方式是什么?

 byte[] input = new byte[5]{1,2,3,4,5};
ArraySegment<byte> delimited = new ArraySegment<byte>(input,0,2);
byte[] segment = HERE I NEED SOMETHING THAT WILL RETURN THE SEGMENT i.e. [0,1,2]

最重要的一点,segment一定不能是copy,而是要引用原数组。如果对段进行了任何更改,它们必须反射(reflect)在原始数组中。

非常感谢任何提示,谢谢!

ASSIGNMENT BENCHMARKS:在 Thomas 的一些回答之后和 digEmAll

好吧,我针对 digEmAll 和 Thomas 的代码运行了一些基准测试,令我惊讶的是代码的速度要快得多。正是我拼命寻找的东西。这是结果。

Construct             Size    Elements assigned    Iterations       Time
_______________________________________________________________________________

ArraySegmentWrapper 1500 1500 1000000 396.3 ms
Array.Copy 1500 1500 1000000 4389.04 ms

正如您所看到的巨大差异,我很清楚我将使用 ArraySegment 的代码。下面是基准测试代码。请注意,这可能有点有偏见的人会争论为什么"new"被放在一个循环中。我只是想重现我目前手头的情况,在不移动大部分代码的情况下尽可能多地解决它。这让我很开心!

namespace ArraySegmentWrapped
{
class Program
{

public static Stopwatch stopWatch = new Stopwatch();
public static TimeSpan span = new TimeSpan();
public static double totalTime = 0.0;
public static int iterations = 1000000;

static void Main(string[] args)
{
int size = 1500;
int startIndex = 0;
int endIndex = 1499;
byte[] array1 = new byte[size];
byte[] array2 = null;

for (int index = startIndex; index < size; index++)
{
array1[index] = (byte)index;
}

ArraySegmentWrapper<byte> arraySeg;

for (int index = 0; index < iterations; index++)
{
stopWatch.Start();
arraySeg = new ArraySegmentWrapper<byte>(array1, startIndex, endIndex);
stopWatch.Stop();
totalTime += stopWatch.Elapsed.TotalMilliseconds;
}

Console.WriteLine("ArraySegment:{0:F6}", totalTime / iterations);
stopWatch.Reset();
totalTime = 0.0;

for (int index = 0; index < iterations; index++)
{
stopWatch.Start();
array2 = new byte[endIndex - startIndex + 1];
Array.Copy(array1, startIndex, array2, 0, endIndex);
stopWatch.Stop();
totalTime += stopWatch.Elapsed.TotalMilliseconds;
}
Console.WriteLine("Array.Copy:{0:F6}", totalTime / iterations);


}
}
// Code for ArraySegmentWrapper goes here

}

访问基准(更新) 那么之后是什么 Thomas指出了基准并说与 ArraySegment 相比,访问简单数组会更快,他是完全正确的。但是由于 digEmAll 指出我应该在 Release模式下进行测试(对于在 Debug模式下进行测试的老错误感到抱歉),我保留了与上面几乎相同的代码(迭代减少了两个零 - 不能等待很长时间才能输出来吧,抱歉)和一些修改以访问相同数量的元素,下面是我得到的。

Construct             Size    Elements accessed    Iterations       Time
_______________________________________________________________________________

ArraySegmentWrapper 1500 1500 1000000 5268.3 ms
Array.Copy 1500 1500 1000000 4812.4 ms

得出的结论是,虽然 assingment 非常快,但通过 ArraySegments 访问速度很慢。

最佳答案

Thomas Levesque's suggestion开始我构建了一个简单的 ArraySegmentWrapper<T>以这种方式使用的类:

static void Main(string[] args)
{
int[] arr = new int[10];
for (int i = 0; i < arr.Length; i++)
arr[i] = i;

// arr = 0,1,2,3,4,5,6,7,8,9

var segment = new ArraySegmentWrapper<int>(arr, 2, 7);
segment[0] = -1;
segment[6] = -1;
// now arr = 0,1,-1,3,4,5,6,7,-1,9


// this prints: -1,3,4,5,6,7,-1
foreach (var el in segment)
Console.WriteLine(el);
}

实现:

public class ArraySegmentWrapper<T> : IList<T>
{
private readonly ArraySegment<T> segment;

public ArraySegmentWrapper(ArraySegment<T> segment)
{
this.segment = segment;
}

public ArraySegmentWrapper(T[] array, int offset, int count)
: this(new ArraySegment<T>(array, offset, count))
{
}

public int IndexOf(T item)
{
for (int i = segment.Offset; i < segment.Offset + segment.Count; i++)
if (Equals(segment.Array[i], item))
return i;
return -1;
}

public void Insert(int index, T item)
{
throw new NotSupportedException();
}

public void RemoveAt(int index)
{
throw new NotSupportedException();
}

public T this[int index]
{
get
{
if (index >= this.Count)
throw new IndexOutOfRangeException();
return this.segment.Array[index + this.segment.Offset];
}
set
{
if (index >= this.Count)
throw new IndexOutOfRangeException();
this.segment.Array[index + this.segment.Offset] = value;
}
}

public void Add(T item)
{
throw new NotSupportedException();
}

public void Clear()
{
throw new NotSupportedException();
}

public bool Contains(T item)
{
return this.IndexOf(item) != -1;
}

public void CopyTo(T[] array, int arrayIndex)
{
for (int i = segment.Offset; i < segment.Offset + segment.Count; i++)
{
array[arrayIndex] = segment.Array[i];
arrayIndex++;
}
}

public int Count
{
get { return this.segment.Count; }
}

public bool IsReadOnly
{
get { return false; }
}

public bool Remove(T item)
{
throw new NotSupportedException();
}

public IEnumerator<T> GetEnumerator()
{
for (int i = segment.Offset; i < segment.Offset + segment.Count; i++)
yield return segment.Array[i];
}

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

编辑:

正如@JeppeStigNielsen 在评论中指出的那样,自 .NET 4.5 ArraySegment<T> 以来工具 IList<T>

关于c# - ArraySegment - 返回实际段 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5756692/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com