2014-09-09 6 views
2

Я хочу подсчитать количество классов во вложенной коллекции, например. [[[1,2], [3,4,5]], [[1,2], [3,4,5]]]. Здесь упомянутый класс «INT» и ожидаемый ответ 10.Как рекурсивно пересечь вложенную общую коллекцию?

сгенерировать этот список, как:

 List<int> list1 = new List<int>(2); 
     list1.Add(1); 
     list1.Add(2); 
     List<int> list2 = new List<int>(3); 
     list2.Add(3); 
     list2.Add(4); 
     list2.Add(5); 

     List<List<int>> listlist = new List<List<int>>(2); 
     listlist.Add(list1); 
     listlist.Add(list2); 

     List<List<List<int>>> listlistlist = new List<List<List<int>>>(2); 
     listlistlist.Add(listlist); 
     listlistlist.Add(listlist); 

Когда я программирую, я предпочитаю писать такой метод для общего класса, мои коды:

public static int CountT<T>(ICollection<T> pTCol, int intLevel = 1) 
    { 
     int intCount = 0; 
     if (intLevel > 0) 
     { 
      intLevel--; 
      foreach (T pT in pTCol) 
      { 
       ICollection<T> subTCol = pT as ICollection<T>; //PROBLEM: I got "null" for subTCol when the program was running 
       intCount += CountT(subTCol, intLevel); 
      } 
     } 
     else if (intLevel == 0) 
     { 
      intCount = pTCol.Count; 
     } 
     return intCount; 
    } 

Я тестировал код выше по

 int intCount = CountT(listlistlist, 2); 

тогда я получил проблему

 ICollection<T> subTCol = pT as ICollection<T>; //PROBLEM: I got "null" for subTCol when the program was running 

Я также попытался коды:

public static int CountT2<T, T2>(ICollection<T> pTCol, int intLevel = 1) 
    { 
     int intCount = 0; 
     if (intLevel > 0) 
     { 
      intLevel--; 
      foreach (T pT in pTCol) 
      { 
       ICollection<T2> subTCol = pT as ICollection<T2>; 
       intCount += CountT2(subTCol, intLevel); //PROBLEM: The type arguments for method cannot be inferred from the usage. Try specifying the type arguments explicitly. (I could not pass the compiling) 
      } 
     } 
     else if (intLevel == 0) 
     { 
      intCount = pTCol.Count; 
     } 
     return intCount; 
    } 

Я не мог пройти составителя

 intCount += CountT2(subTCol, intLevel); //PROBLEM: The type arguments for method cannot be inferred from the usage. Try specifying the type arguments explicitly. (I could not pass the compiling) 

Как я могу это сделать?

+1

Вы всегда имеют три уровня, или произвольное число? – AakashM

+0

В моей практической проблеме у меня есть только два уровня, но я хочу реализовать общий метод, то есть я хочу иметь метод, который может обрабатывать произвольное количество уровней. – pengdlzn

+0

Я бы предположил, что для произвольного количества уровней соответствующая структура данных является ** деревом **, для которого алгоритмы гораздо более понятны. – AakashM

ответ

1

ICollection subTCol = рТ, как ICollection // ПРОБЛЕМА: Я получил "нуль" для subTCol

Причины этого является Нулевым pT не является ICollection<T>, потому что T является int и listlistlist является List<List<List<T>>>. Поэтому pT - это List<List<T>>, поэтому, если вы попытаетесь отдать его ICollection<T>, вы получите нулевое значение.

Я хочу подсчитать количество элементов в вложенной коллекции.

Вы можете сделать это намного проще, используя метод Sum. Если вы знаете, уровень вложенности, например:

Assert.AreEqual(10, listlistlist.Sum(x => x.Sum(y => y.Count))); 

Если вы не знаете уровень вложенности или вы хотите более универсальный метод, вы можете создать метод расширения, как:

public static class RecursiveSumExtension 
{ 
    public static int RecursiveSum(this IEnumerable items) 
    { 
     if (null == items) 
      return 0; 

     var total = 0; 

     foreach (var item in items) 
     { 
      if (item is IEnumerable) 
       total += (item as IEnumerable).RecursiveSum(); 

      else 
       total++; 
     } 

     return total; 
    } 
} 

и тест:

Assert.AreEqual(10, listlistlist.RecursiveSum()); 

Список поколение

Как быстро в сторону, вы можете использовать «s коллекции синтаксис инициализации, чтобы сделать код немного более читаемым при создании коллекции:

 var listlist = new List<List<int>> 
     { 
      new List<int> {1, 2}, 
      new List<int> {3, 4, 5} 
     }; 

     var listlistlist = new List<List<List<int>>> 
     { 
      listlist, 
      listlist 
     }; 
+0

Мне нужно добавить 'using System.Collections;' в верхней части класса, если я хочу использовать 'IEnumerable'. – pengdlzn

+0

Это правильно. –