Вопрос по коллекциям

115
19 ноября 2021, 00:10

Возможно ли сделать динамическую коллекцию по ширине ? Если да, как это называется ? Не могу найти... чтобы ознакомиться. По ширине имеется ввиду, как двумерный массив, только с возможностью расширения.

UPD: @EvgeniyZ подсказал использовать List<List<T>>

Вот как раз стал осваивать и то что нужно мне xD. Но смущает 1 момент - картинка ниже - только так можно перебирать ?

        private void button1_Click(object sender, EventArgs e)
        {
            test();
        }
        private void test() 
        {
            List<List<string>> KollekciyaKollekcij = new List<List<string>>();
            List<string> list1 = new List<string>() { "1", "2", "3", "4", "5" };
            List<string> list2 = new List<string>() { "1", "2", "3", "4", "5" };
            List<string> list3 = new List<string>() { "1", "2", "3", "4", "5" };
            List<string> list4 = new List<string>() { "1", "2", "3", "4", "5" };
            List<string> list5 = new List<string>() { "1", "2", "3", "4", "5" };
            KollekciyaKollekcij.Add(list1);
            KollekciyaKollekcij.Add(list2);
            KollekciyaKollekcij.Add(list3);
            KollekciyaKollekcij.Add(list4);
            KollekciyaKollekcij.Add(list5);

            int i = 0;
            foreach (var item1 in KollekciyaKollekcij)
            {
                i++;
                foreach (var item2 in KollekciyaKollekcij[i-1])
                {
                    textBox1.AppendText(item2);
                }
                textBox1.AppendText(Environment.NewLine);
            }
        }

Answer 1

Можно конечно использовать предложенный в комментарии вариант List<List<T>>, но поведение будет сильно отличаться от прямоугольного массива. В большинстве случаев такого поведения вполне достаточно.

Если же вам нужен настоящий прямоугольный массив переменного размера, можно использовать что-то вроде такой конструкции:

class Matrix2d<T>
{
    public int SizeX { get; private set; }
    public int SizeY { get; private set; }
    private readonly Dictionary<(int x, int y), T> _cells = new Dictionary<(int x, int y), T>();
    public Matrix2d(int sizeX, int sizeY)
    {
        SizeX = sizeX;
        SizeY = sizeY;
    }
    public T this[int x, int y]
    {
        get
        {
            if (x < 0 || x >= SizeX)
                throw new ArgumentOutOfRangeException(nameof(x));
            if (y < 0 || y >= SizeY)
                throw new ArgumentOutOfRangeException(nameof(y));
            return _cells.TryGetValue((x, y), out T value) ? value : default(T);
        }
        set
        {
            if (x < 0 || x >= SizeX)
                throw new ArgumentOutOfRangeException(nameof(x));
            if (y < 0 || y >= SizeY)
                throw new ArgumentOutOfRangeException(nameof(y));
            _cells[(x, y)] = value;//если ключ есть в словаре, значение будет обновлено 
                                   //иначе создана новая запись с указанным ключом
        }
    }
    public void ChangeSizeX(int newValue)
    {
        if (newValue < SizeX)
        {
            foreach (var positionForClean in _cells.Keys.Where(i => i.x >= newValue).ToArray())
                _cells.Remove(positionForClean);
        }
        SizeX = newValue;
    }
    public void ChangeSizeY(int newValue)
    {
        if (newValue < SizeY)
        {
            foreach (var positionForClean in _cells.Keys.Where(i => i.y >= newValue).ToArray())
                _cells.Remove(positionForClean);
        }
        SizeY = newValue;
    }
}

Использование:

Matrix2d<int> test = new Matrix2d<int>(5, 5);
for (int x = 0; x < test.SizeX; x++)
    for (int y = 0; y < test.SizeY; y++)
        Console.WriteLine(test[x, y]);

Это только заготовка. К ней можно прикрутить реализацию интерфейсов ICollection<T> и IEnumerable<T> для того чтобы сделать полноценной коллекцией.

Данный вариант гарантирует прямоугольность по индексам и позволяет эффективно работать большими разреженными матрицами, т.к. хранятся только значения, отличные от значения по-умолчанию для указанного типа.

Для матриц малого размера такая конструкция будет избыточной, не измерял, но просто пересоздать обычный двумерный массив и скопировать туда данные из предыдущего может оказаться эффективнее.

Для больших матриц заполненных полностью, вопрос спорный, с одной стороны этот вариант проиграет по используемой памяти, с другой, если вам важна возможность свободно менять размер матрицы, может значительно выиграть за счет отсутствия необходимости переписывать всю матрицу целиком при изменении размера. В данном случае увеличение размера практически бесплатное, а уменьшение требует времени только на удаление элементов за пределами нового размера.

Использовать или нет - решать вам. Если кто-то захочет измерить производительность в сравнении с обычным прямоугольным массивом, поделитесь результатами, будет очень интересно сравнить.

READ ALSO
Преобразовать дату yy/mm/dd в yy/mm

Преобразовать дату yy/mm/dd в yy/mm

В ASPNET приложении я получаю дату из базы данных таким методом:

176
Запрос на выборку из 2-х таблиц SQL

Запрос на выборку из 2-х таблиц SQL

Есть две таблицы вида:

103
Вращение изображения c#

Вращение изображения c#

Всем привет, Сразу к делу : Моя задача вращать картинку в pictureBox (есть ракета, она должна плавно отклоняться на угол от -30° до 30° в зависимости...

101