Развернуть массив массивов
От: astel  
Дата: 29.06.08 05:36
Оценка:
Есть массив object[]
элементы в свою очередь могут быть массивами ( т.е. всего м.б. не более 2 уровней вложенности )
Нужно развернуть исходный массив так чтобы получить всевозможные комбинации элементов вложенных массивов.

Поясню на примере , допустим исх. массив имеет 3 элемента

{ {a1} , {b1,b2}, {c1,c2,c3} }


На выходе нужно получить следующие массивы ( каждый из которых тоже будет иметь по 3 элемента )

{ a1 , b1, c1 }
{ a1 , b1, c2 }
{ a1 , b1, c3 }
{ a1 , b2, c1 }
{ a1 , b2, c2 }
{ a1 , b2, c3 }

Как это можно элегантно сделать. если размеры всех массивов заранее не известны ( т.е. все они object[] ) ?
Может как-то можно yield return задействовать ?
Re: Развернуть массив массивов
От: Аноним  
Дата: 29.06.08 07:21
Оценка:
Здравствуйте, astel, Вы писали:

A>Как это можно элегантно сделать. если размеры всех массивов заранее не известны ( т.е. все они object[] ) ?


А типы элемнтов вложенных массивов до приведения к object известны?
Re: Развернуть массив массивов
От: desco США http://v2matveev.blogspot.com
Дата: 29.06.08 09:08
Оценка:
Здравствуйте, astel, Вы писали:

<skipped/>

например так:

    class Program
    {
        static void Main()
        {
            var arr = new object[]
                          {
                              "a1",
                              new object[] {"b1", "b2"},
                              new object[] {"c1", "c2", "c3"}, 
                          };

            foreach (var objects in Enumerate(arr))
                Print(objects);
        }

        private static IEnumerable<T> One<T>(T obj)
        {
            yield return obj;
        }

        private static IEnumerable<IEnumerable<object>> Enumerate(object[] arr, int dim)
        {
            if (dim == arr.Length)
                yield return Enumerable.Empty<object>();
            else
            {
                var inner = arr[dim] as object[];
                foreach (var objects in Enumerate(arr, dim + 1))
                {
                    if (inner != null)
                    {
                        foreach (var o in inner)
                        {
                            yield return One(o).Concat(objects);
                        }
                    }
                    else
                    {
                        yield return One(arr[dim]).Concat(objects);
                    }
                }
            }
        }

        static IEnumerable<object[]> Enumerate(object[] arr)
        {
            foreach (var objects in Enumerate(arr, 0))
            {
                yield return objects.ToArray();
            } 
        }

        static void Print(IEnumerable<object> arr)
        {
            var str = arr.Aggregate(new StringBuilder(), (sb, v) => sb.AppendFormat(" {0}", v)).ToString();
            Console.WriteLine(str);
        }
    }



a1 b1 c1
a1 b2 c1
a1 b1 c2
a1 b2 c2
a1 b1 c3
a1 b2 c3

Re: Развернуть массив массивов
От: Alexey M.  
Дата: 29.06.08 09:20
Оценка:
Здравствуйте, astel, Вы писали:

A>skipped


Вот что получилось


using System;
using System.Linq;

class Program
{
    static object[][] Flat(object[][] array, int index)
    {
        if (index == array.Length - 1)
            return array[index].Select(e => new[] { e }).ToArray();

        return
            (from e in array[index]
             from i in Flat(array, index + 1)
             select new[] { e }.Concat(i).ToArray()
            ).ToArray();
    }

    static object[][] Flat(object[][] array)
    {
        return Flat(array, 0);
    }

    static void Main(string[] args)
    {
        object[][] array = new[]{
            new [] {"a1"},
            new [] {"b1","b2"},
            new [] {"c1","c2","c3"}
        };

        object[][] flat = Flat(array);
    }
}
Re[2]: Развернуть массив массивов
От: astel  
Дата: 01.07.08 02:26
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, astel, Вы писали:


A>>Как это можно элегантно сделать. если размеры всех массивов заранее не известны ( т.е. все они object[] ) ?


А>А типы элемнтов вложенных массивов до приведения к object известны?


Не понял вопрос. На входе есть object[] ... это все что извеснто .... типы (если они нужны) можно на лету ведь узнать
ю
Re[2]: Развернуть массив массивов
От: Аноним  
Дата: 01.07.08 02:30
Оценка:
Здравствуйте, Alexey M., Вы писали:

AM>Здравствуйте, astel, Вы писали:


A>>skipped


AM>Вот что получилось


Я немного не правильно сформулировал — на входе не object[][] , а object[]
Re[3]: Развернуть массив массивов
От: Alexey M.  
Дата: 01.07.08 08:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Я немного не правильно сформулировал — на входе не object[][] , а object[]


Тогда вот так получится


using System;
using System.Linq;
using System.Collections.Generic;

class Program
{
    static object[][] Flat(object[] array, int index)
    {
        var currentDimension = 
            array[index] is IEnumerable<object> ?
                (IEnumerable<object>) array[index] :
                new [] { array[index] };

        if (index == array.Length - 1)
            return currentDimension.Select(e => new[] { e }).ToArray();

        return
            (from e in currentDimension
             from i in Flat(array, index + 1)
             select new[] { e }.Concat(i).ToArray()
            ).ToArray();
    }

    static object[][] Flat(object[] array)
    {
        return Flat(array, 0);
    }

    static void Main(string[] args)
    {
        object[] array = new object[]{
            "some object",
            new [] {"b1","b2"},
            new [] {"c1","c2","c3"},
            "yet another object",
            new [] {"d1","d2","d3","d4"}
        };

        object[][] flat = Flat(array);
    }
}
Re: Развернуть массив массивов
От: Lloyd Россия  
Дата: 09.07.09 18:04
Оценка:
Здравствуйте, astel, Вы писали:

A>Как это можно элегантно сделать. если размеры всех массивов заранее не известны ( т.е. все они object[] ) ?

A>Может как-то можно yield return задействовать ?

static object[][] Zip(object[] data) {
    var enumData = from d in data.OfType<IEnumerable>()
                   select d.OfType<object>();

    var q = from line in Zip(enumData)
            select line.ToArray();
    return q.ToArray();
}

static IEnumerable<IEnumerable<T>> Zip<T>(IEnumerable<IEnumerable<T>> data) {
    var q = from i in Enumerable.Range(0, int.MaxValue/2)
            select Slice(data, i);
    return q.TakeWhile(_ => _.Any());
}

static IEnumerable<T> Slice<T>(IEnumerable<IEnumerable<T>> data, int i) {
    return from arr in data
           where arr.Count() > i
           select arr.ElementAt(i);
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.