Общий индекс для ступенчатых массивов

У меня есть массив arr[][], он ступенчатый, как я могу сделать, чтобы для доступа к его элементам нужен был только один индекс.

введите сюда описание изображения

Пример:

Если взять индекс [1][2] == [5] или [0][3] == [3]


Ответы (3 шт):

Автор решения: timur
static class ArrayExtensions {
    public static T GetValueAt<T>(this T[][] arr, int index) {
        int currentIndex = 0;
        foreach (T[] arr1 in arr) {
            foreach (T i in arr1) {
                if (currentIndex == index)
                    return i;
                currentIndex++;
            }
        }
        throw new IndexOutOfRangeException();
    }
}

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

int[][] arr = new int[][] { new int[] { 0, 1, 2, 3 }, new int[] { 4, 5, 6 } };

Console.WriteLine(arr.GetValueAt(5)); //=> 5
→ Ссылка
Автор решения: Aimon Z.
    int[][] arr = new int[3][] { new int[] { 0, 1, 2, 3, 4 }, new int[] { 5, 6, 7, 8 }, new int[] { 9, 10, 11 } };

    int i = 0;
    for ( ; ; )
    {
        int ind = index;

        if ((ind -= arr[i].Length) < 0)
        {
            break;
        }

        i++;

        index = ind;
    }

    return arr[i][index];
→ Ссылка
Автор решения: Grundy

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

Решение может быть только одно: идти по массивы и считать элементы.

Реализация может быть в лоб:

arr.SelectMany(cur => cur)
   .ElementAt(index)

Где SelectMany делает массив плоским, а ElementAt берет элемент по указанному индексу.

Улучшить можно, если не считать каждый элемент, а сразу оценивать в каком из массивов расположен элемент

static T ByIndex2<T>(T[][] arr, int index)
{
    foreach (var item in arr)
    {
        if (index - item.Length < 0) // если разница меньше 0, значит нашли массив, а index соответствует индексу нужного элемента в найденном массиве
        {
            return item[index];
        }
        index -= item.Length;
    }

    throw new IndexOutOfRangeException(nameof(index));
}
→ Ссылка