using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication14 {
public static class FoldHelper {
private enum ItemType {
Object,
Enuemrable
}
private static IEnumerable<T> DeepFold<T>(System.Collections.IEnumerable sequence, Dictionary<Type, ItemType> type_set) {
foreach (object item in sequence) {
Type item_type = item.GetType();
ItemType item_type_tag;
if (!type_set.TryGetValue(item_type, out item_type_tag)) {
item_type_tag = (item is System.Collections.IEnumerable) ?
ItemType.Enuemrable
: ItemType.Object;
type_set.Add(item_type, item_type_tag);
}
switch (item_type_tag) {
case ItemType.Enuemrable:
foreach (T sub_item in DeepFold<T>((System.Collections.IEnumerable)item, type_set))
yield return sub_item;
break;
case ItemType.Object:
yield return (T)item;
break;
}
}
}
public static IEnumerable<T> DeepFold<T>(System.Collections.IEnumerable sequence) {
return DeepFold<T>(sequence, new Dictionary<Type, ItemType>());
}
}
class Program {
static void Main(string[] args) {
foreach (int number in FoldHelper.DeepFold<int>(new object[] {
new int[] { 1, 2, 3, 4},
new int[] { 5, 6, 7 },
new int[] { 8, 9 },
new object[] { 10, 11, new int[] { 12, 13, 14 } },
15,
16,
17
})) {
Console.WriteLine(number);
}
Console.ReadLine();
}
}
}
IEnumerator во вложенных коллекциях
Имеем T[][]..........[] where T: IEnumerable и нужно это перевести в T[]
То есть многомерный массив в одномерный, причем упорядоченно.
С задачей справиля следующим образом:
Код:
public static IEnumerable GetIEnumerator<T>(this IEnumerable<T> obj)
where T: IEnumerable
{
Queue<IEnumerable> Qu = new Queue<IEnumerable>();
if (obj != null)
{
Qu.Enqueue(obj);
while (Qu.Count > 0)
{
foreach (object ie in Qu.Peek())
{
if (ie is IEnumerable) Qu.Enqueue(ie as IEnumerable);
else yield return ie;
}
Qu.Dequeue();
}
}
}
where T: IEnumerable
{
Queue<IEnumerable> Qu = new Queue<IEnumerable>();
if (obj != null)
{
Qu.Enqueue(obj);
while (Qu.Count > 0)
{
foreach (object ie in Qu.Peek())
{
if (ie is IEnumerable) Qu.Enqueue(ie as IEnumerable);
else yield return ie;
}
Qu.Dequeue();
}
}
}
Но вот такой примерчик:
Код:
var F = new object[][]{
new object[]{1,2,3},
new object[]{5,6, new int[]{7,8,9},10},
new object[]{11,12,13}
};
new object[]{1,2,3},
new object[]{5,6, new int[]{7,8,9},10},
new object[]{11,12,13}
};
Вывелся как:
1, 2, 3, 5, 6, 10, 11, 12, 13, 7, 8, 9,
Т.е. сначала обработался уровень вложений 1, затем 2, затем 3.
Должно вывестись:
1, 2, 3, 5, 6, , 7, 8, 9, 10, 11, 12, 13
Буду благодарен за идеи!!!
Код:
public static IEnumerable GetIEnumerator(this IEnumerable obj)
{
if (obj != null)
{
Stack<IEnumerator> stk = new Stack<IEnumerator>();
stk.Push(obj.GetEnumerator());
while (stk.Count > 0)
{
while (stk.Peek().MoveNext())
{
if (stk.Peek().Current is IEnumerable)
stk.Push((stk.Peek().Current as IEnumerable).GetEnumerator());
else yield return stk.Peek().Current;
}
stk.Pop();
}
}
}
{
if (obj != null)
{
Stack<IEnumerator> stk = new Stack<IEnumerator>();
stk.Push(obj.GetEnumerator());
while (stk.Count > 0)
{
while (stk.Peek().MoveNext())
{
if (stk.Peek().Current is IEnumerable)
stk.Push((stk.Peek().Current as IEnumerable).GetEnumerator());
else yield return stk.Peek().Current;
}
stk.Pop();
}
}
}
Но если кто знает лучше способ - буду премного благодарен!!!
Цитата: sigmov
Но если кто знает лучше способ - буду премного благодарен!!!
Вот мой вариант.
Код:
Но всеравно это затратный метод.. нужно бы измерить его производительность профайлером.
Код:
public static IEnumerable<T> DeepFold<T>(System.Collections.IEnumerable sequence) {
foreach (object item in sequence) {
if (item is System.Collections.IEnumerable) {
foreach (T sub_item in DeepFold<T>((System.Collections.IEnumerable)item))
yield return sub_item;
} else {
yield return (T)item;
}
}
}
foreach (object item in sequence) {
if (item is System.Collections.IEnumerable) {
foreach (T sub_item in DeepFold<T>((System.Collections.IEnumerable)item))
yield return sub_item;
} else {
yield return (T)item;
}
}
}