【问题标题】:Redefine massive of fixed size重新定义固定大小的海量
【发布时间】:2013-11-19 17:17:26
【问题描述】:

我的数组大小为 10。它必须包含传入参数的最后十个值(传入参数的数量接近 3k)我在以下循环中有一些逻辑:

for (int i=0; i<incomingLength; i++)
{
 //and here I also need to rewrite this array size of 10 with new incomingValue(i)
}

也许它很原始,但我被卡住了((

【问题讨论】:

  • 那么问题是什么?
  • 您是在问我们如何构建“向后迭代循环”?
  • stackoverflow.com/q/13275975/251311 和几十篇在互联网上的好文章,如果你使用“c# 循环缓冲区”关键字进行谷歌搜索
  • @varocarbas 无需向后迭代 - 只需从 incomingLength - 10 开始
  • @MarcGravell 是的,当然。我这么说是为了概括地说明这一点:)(因为仍然不知道这是否是 OP 想要的)

标签: c# arrays math


【解决方案1】:

您可以为此使用“循环缓冲区”。

这是一个示例实现(为简洁起见,省略了参数验证):

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace Demo
{
    public class CircularBuffer<T>: IEnumerable<T>
    {
        /// <summary>Constructor.</summary>
        /// <param name="capacity">The maximum capacity of the buffer.</param>

        public CircularBuffer(int capacity)
        {
            // The reason for this +1 is to simplify the logic - we can use "front == back" to indicate an empty buffer.

            _buffer = new T[capacity+1];
        }

        /// <summary>The buffer capacity.</summary>

        public int Capacity
        {
            get
            {
                return _buffer.Length - 1;
            }
        }

        /// <summary>The number of elements currently stored in the buffer.</summary>

        public int Count
        {
            get
            {
                int result = _back - _front;

                if (result < 0)
                    result += _buffer.Length;

                return result;
            }
        }

        /// <summary>Is the buffer empty?</summary>

        public bool IsEmpty
        {
            get
            {
                return this.Count == 0;
            }
        }

        /// <summary>Is the buffer full? (i.e. has it reached its capacity?)</summary>

        public bool IsFull
        {
            get
            {
                return nextSlot(_back) == _front;
            }
        }

        /// <summary>Empties the buffer.</summary>

        public void Empty()
        {
            _front = _back = 0;
            Array.Clear(_buffer, 0, _buffer.Length); // Destroy any old references so they can be GCed.
        }

        /// <summary>Add an element to the buffer, overwriting the oldest element if the buffer is full.</summary>
        /// <param name="newItem">The element to add.</param>

        public void Add(T newItem)
        {
            _buffer[_back] = newItem;
            _back = nextSlot(_back);

            if (_back == _front) // Buffer is full?
            {
                _front = nextSlot(_front); // Bump the front, overwriting the current front.
                _buffer[_back] = default(T); // Remove the old front value.
            }
        }

        /// <summary>
        /// The typesafe enumerator. Elements are returned in oldest to newest order.
        /// This is not threadsafe, so if you are enumerating the buffer while another thread is changing it you will run
        /// into threading problems. Therefore you must use your own locking scheme to avoid the problem.
        /// </summary>

        public IEnumerator<T> GetEnumerator()
        {
            for (int i = _front; i != _back; i = nextSlot(i))
                yield return _buffer[i];
        }

        /// <summary>The non-typesafe enumerator.</summary>

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator(); // Implement in terms of the typesafe enumerator.
        }

        /// <summary>Calculates the index of the slot following the specified one, wrapping if necessary.</summary>

        private int nextSlot(int slot)
        {
            return (slot + 1) % _buffer.Length;
        }

        /// <summary>
        /// The index of the element at the front of the buffer. 
        /// If this equals _back, the buffer is empty.
        /// </summary>

        private int _front;

        /// <summary>
        /// The index of the first element BEYOND the last used element of the buffer. 
        /// Therefore this indicates where the next added element will go.
        /// </summary>

        private int _back;

        /// <summary>The underlying buffer. This has a length one greater than the actual capacity.</summary>

        private readonly T[] _buffer;
    }

    internal class Program
    {
        private void run()
        {
            CircularBuffer<int> buffer = new CircularBuffer<int>(10);

            for (int i = 0; i < 20; ++i)
                buffer.Add(i);

            foreach (int n in buffer)
                Console.WriteLine(n);  // Prints 10..19
        }

        private static void Main()
        {
            new Program().run();
        }
    }
}

【讨论】:

  • 谢谢你,马修——这就是我要找的东西))我没有时间调查更多,所以我只做 if(count>10){arr[i]= val[i]; arr[i-1]= val[i-1];....} 你的解决方案很优雅)))
【解决方案2】:

使用array.copy

var arr1 = new int[] { 1, 2, 3};
var arr2 = new int[] { 4, 5};

var target = new int[arr1.Length + arr2.Length];
Array.Copy(arr1, target, arr1.Length);
Array.Copy(arr2, 0, target, arr1.Length, arr2.Length);

这将合并两个数组。您可以根据需要修改索引

【讨论】:

    猜你喜欢
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2012-03-17
    • 2012-03-31
    • 1970-01-01
    相关资源
    最近更新 更多