UFO ET IT

C #에서 배열을 추가하는 가장 효율적인 방법은 무엇입니까?

ufoet 2020. 11. 22. 20:57
반응형

C #에서 배열을 추가하는 가장 효율적인 방법은 무엇입니까?


나는 구식 ActiveX에서 double 배열 형태로 데이터를 가져오고 있습니다. 처음에는 실제로 검색 할 최종 샘플 수를 알지 못합니다.

시스템에서 이러한 배열을 가져올 때 C #에서 이러한 배열을 함께 연결하는 가장 효율적인 방법은 무엇입니까?


실제 배열에 추가 할 수 없습니다. 배열의 크기는 생성시 고정됩니다. 대신 List<T>필요에 따라 확장 할 수 있는 a 사용하십시오 .

또는 배열 목록을 유지하고 모든 것을 확보 한 경우에만 모두 연결하십시오.

내가 현실적으로 제공 할 수있는 것보다 더 자세한 정보와 통찰력 은 어레이에 대한 Eric Lippert의 블로그 게시물을 참조하십시오. :)


세 번째 배열로 결합하려는 동일한 유형의 배열 2 개가 있다면이를 수행하는 매우 간단한 방법이 있습니다.

코드는 다음과 같습니다.

String[] theHTMLFiles = Directory.GetFiles(basePath, "*.html");
String[] thexmlFiles = Directory.GetFiles(basePath, "*.xml");
List<String> finalList = new List<String>(theHTMLFiles.Concat<string>(thexmlFiles));
String[] finalArray = finalList.ToArray();

여기에있는 대답을 권장합니다. C #에서 두 배열을 어떻게 연결합니까?

예 :

var z = new int[x.Length + y.Length];
x.CopyTo(z, 0);
y.CopyTo(z, x.Length);

.Net 4에서 표준으로 제공되는 linq 확장을 사용하면 배열을 간단하게 연결할 수 있습니다.

기억해야 할 가장 큰 것은 linq가 IEnumerable<T>객체 와 함께 작동 하므로 배열을 결과로 되돌리려 .ToArray()면 마지막에 메서드 를 사용해야한다는 것입니다.

2 바이트 배열 연결의 예 :

byte[] firstArray = {2,45,79,33};
byte[] secondArray = {55,4,7,81};
byte[] result = firstArray.Concat(secondArray).ToArray();

이 솔루션은 매우 재미있어 보이지만 두 개의 문으로 배열을 연결할 수 있습니다. 큰 바이트 배열을 처리 할 때 링크 된 목록을 사용하여 각 바이트를 포함하는 것이 비효율적이라고 생각합니다.

다음은 스트림에서 바이트를 읽고 즉시 바이트 배열을 확장하는 코드 샘플입니다.

    byte [] buf = 새로운 byte [8192];
    byte [] 결과 = 새로운 byte [0];
    정수 개수 = 0;
    하다
    {
        count = resStream.Read (buf, 0, buf.Length);
        if (count! = 0)
        {
            Array.Resize (ref result, result.Length + count);
            Array.Copy (buf, 0, result, result.Length-개수, 개수);
        }
    }
    while (count> 0); // 읽을 데이터가 더 있습니까?
    resStream.Close ();

이를 사용하여 루프없이 두 개의 배열을 추가 할 수 있습니다.

나는 당신이 배열 중 하나로 결합하려는 동일한 유형의 2 개의 배열이 있다면 그것을 수행하는 매우 간단한 방법이 있다고 믿습니다.

코드는 다음과 같습니다.

String[] TextFils = Directory.GetFiles(basePath, "*.txt");
String[] ExcelFils = Directory.GetFiles(basePath, "*.xls");
String[] finalArray = TextFils.Concat(ExcelFils).ToArray();

또는

String[] Fils = Directory.GetFiles(basePath, "*.txt");
String[] ExcelFils = Directory.GetFiles(basePath, "*.xls");
Fils = Fils.Concat(ExcelFils).ToArray();

마지막에있을 항목 수를 대략적으로 계산할 수 있다면 count를 매개 변수로 사용하는 List 생성자의 오버로드를 사용하십시오. 값 비싼 목록 중복을 저장합니다. 그렇지 않으면 비용을 지불해야합니다.


최종 결과를 연속 배열로 연결할 필요가 없습니다. 대신 Jon이 제안한대로 목록에 계속 추가하십시오. 결국 당신은 들쭉날쭉 한 배열 (사실상 거의 직사각형)을 갖게 될 것 입니다. 인덱스로 요소에 액세스해야하는 경우 다음 인덱싱 체계를 사용하십시오.

double x = list[i / sampleSize][i % sampleSize];

들쭉날쭉 한 배열에 대한 반복도 간단합니다.

for (int iRow = 0; iRow < list.Length; ++iRow) {
  double[] row = list[iRow];
  for (int iCol = 0; iCol < row.Length; ++iCol) {
    double x = row[iCol];
  }
}

이렇게하면 요소 액세스 속도가 약간 느려지면서 메모리 할당 및 복사가 절약됩니다. 이것이 순 성능 향상인지 여부는 데이터 크기, 데이터 액세스 패턴 및 메모리 제약에 따라 다릅니다.


콘스탄틴이 말한 것을 기반으로 한 유용한 클래스는 다음과 같습니다.

class Program
{
    static void Main(string[] args)
    {
        FastConcat<int> i = new FastConcat<int>();
        i.Add(new int[] { 0, 1, 2, 3, 4 });
        Console.WriteLine(i[0]);
        i.Add(new int[] { 5, 6, 7, 8, 9 });
        Console.WriteLine(i[4]);

        Console.WriteLine("Enumerator:");
        foreach (int val in i)
            Console.WriteLine(val);

        Console.ReadLine();
    }
}

class FastConcat<T> : IEnumerable<T>
{
    LinkedList<T[]> _items = new LinkedList<T[]>();
    int _count;

    public int Count
    {
        get
        {
            return _count;
        }
    }

    public void Add(T[] items)
    {
        if (items == null)
            return;
        if (items.Length == 0)
            return;

        _items.AddLast(items);
        _count += items.Length;
    }

    private T[] GetItemIndex(int realIndex, out int offset)
    {
        offset = 0; // Offset that needs to be applied to realIndex.
        int currentStart = 0; // Current index start.

        foreach (T[] items in _items)
        {
            currentStart += items.Length;
            if (currentStart > realIndex)
                return items;
            offset = currentStart;
        }
        return null;
    }

    public T this[int index]
    {
        get
        {
            int offset;
            T[] i = GetItemIndex(index, out offset);
            return i[index - offset];
        }
        set
        {
            int offset;
            T[] i = GetItemIndex(index, out offset);
            i[index - offset] = value;
        }
    }

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
        foreach (T[] items in _items)
            foreach (T item in items)
                yield return item;
    }

    #endregion

    #region IEnumerable Members

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

    #endregion
}

Olmo's suggestion is very good, but I'd add this: If you're not sure about the size, it's better to make it a little bigger than a little smaller. When a list is full, keep in mind it will double its size to add more elements.

For example: suppose you will need about 50 elements. If you use a 50 elements size and the final number of elements is 51, you'll end with a 100 sized list with 49 wasted positions.

참고URL : https://stackoverflow.com/questions/304816/most-efficient-way-to-append-arrays-in-c

반응형