2016-06-01 6 views
2

"Text1", "Text2", 새 UndefinedInfo ("Undfined1"), 새 UndefinedInfo ("Undfined2"), 새 UndefinedInfo ("Undefined3")와 같은 개체 목록이 있습니다. 텍스트 1, 텍스트 2 1 - - Undefined1이 Undefined2, Undefined3 2 - 내가 관리 텍스트 3스플릿 개체 유형에 따른 개체 목록

작성 //에게 목록>

출력 : "텍스트 3"

나는 다음과 같이 출력이 필요합니다 아래의 기능은 나쁘지만 어떻게 든 잘 작동합니다. TakeWhile 또는 SkipWhile 또는 yield를 사용하여 LINQ 확장을 사용하여 동일한 결과를 얻을 수있는 방법이 있습니까?

public static List<List<object>> PartitionByTypes(List<object> values) 
{ 
List<List<object>> partitionedList = new List<List<object>>(); 

     int j; 
     for (int i = 0; i < values.Count; i++) 
     { 
      j = i; 
      List<object> subList = new List<object>(); 
      Type t = values[j].GetType(); 
      do 
      { 
       subList.Add(values[j]); 
       j++; 
       if (j == values.Count) 
       { 
        break; 
       } 
      } while (values[j].GetType() == t); 
      partitionedList.Add(subList); 
      i = j - 1; 
     } 

     return partitionedList; 
    } 
+1

이 시도 = string.Join (","partitionedList.Select을 (문자열 출력 X => x.ToString()) .ToArray()); – jdweng

+0

마침내 partitionedList를 채우고 있습니다. 솔루션이 어떻게 작동할까요? 샘플 입력과 출력을 제공 할 수 있습니까? – Abhay

+0

출력은 CSV 문자열입니다 (각 배열 항목은 쉼표로 구분됩니다). 내 코드는 목록을 통해 각 항목을 문자열로 변환 한 다음 문자열 JOIN 메서드를 사용하여 각 항목 사이에 쉼표를 넣습니다. 파티션 목록 대신 값을 사용해야합니다. – jdweng

답변

0

그럼 당신은 LINQ와 TakeWhile이 작업을 수행 할 수 있지만, 그 일반 foreach는보다 더 좋을 것입니다 의심 : 어떤 도움을 매우 높이 평가. 예를 들어 :

public static List<List<object>> PartitionByTypes(List<object> values) { 
    var batches = new List<List<object>>(); 
    object prev = null; 
    var batch = new List<object>(); 
    foreach (var value in values) { 
     if (prev != null && prev.GetType() != value.GetType()) { 
      batches.Add(batch); 
      batch = new List<object>(); 
     } 
     batch.Add(value); 
     prev = value; 
    } 
    if (batch.Count > 0) 
     batches.Add(batch); 

    return batches; 
} 
+0

목록에서 유형별로 정렬되지 않은 한 동일한 유형의 모든 인스턴스를 일괄 처리로 그룹화하지 않습니다. –

+0

전체적인 점은 이해합니다. 동일한 유형의 모든 순차적 개체를 별도의 그룹으로 나눕니다. – Evk

+0

첫 번째 방법에서 '배치 반환;'을 잊어 버렸습니다. – juharr

2

다음은 당신이 yield을 사용하여 원하는 일을 할 것입니다 :

public static List<List<object>> LinqPartitionByTypes(List<object> values) 
{ 
    var batches = new List<List<object>>(); 
    while (true) 
    { 
     object prev = null; 
     var batch = values.Skip(batches.Sum(c => c.Count)).TakeWhile(c => { 
       var result = prev == null || prev.GetType() == c.GetType(); 
       prev = c; 
       return result; 
     }).ToList(); 
     if (batch.Count == 0) 
       break; 
     batches.Add(batch); 
    } 
    return batches; 
} 

그러나 나는 더 더 간단하고 깨끗한 일을 할 것입니다. 따라서 반품은 대신 IEnumerable<List<object>>이됩니다.

public static IEnumerable<List<object>> PartitionByTypes(List<object> values) 
{ 
    Type prevType = null; 
    List<object> cache = new List<object>(); 
    foreach (var value in values) 
    { 
     if(prevType != null && value.GetType() != prevType) 
     { 
      yield return cache; 
      cache = new List<object>(); 
     } 

     cache.Add(value); 
     prevType = value.GetType(); 
    } 

    if(cache.Count > 0) 
     yield return cache; 
} 

은 또한 다음과 같은 LINQ 쿼리를 사용할 수

public static IEnumerable<List<object>> PartitionByTypes(List<object> values) 
{ 
    int count = 0; 
    return values.Select((o, i) => new 
     { 
      Object = o, 
      Group = (i == 0 || o.GetType() == values[i - 1].GetType()) ? count : ++count 
     }) 
     .GroupBy(x => x.Group) 
     .Select(g => g.Select(x => x.Object).ToList()); 
} 
+0

이것은 입력 목록의 마지막 요소를 건너 뜁니다. 즉, 목록 2 개를 반환 할 것입니다. – Abhay

+0

@Abhay 마지막에'if (cache.Count> 0) yield yield cache; '로 해결했습니다. – juharr

+0

@juharr ... perfect ... :) 해결책을 주셔서 감사합니다 – Abhay

0
static Type GetObjectTypeOrNull(object o) 
{ 
    return o == null ? null : o.GetType(); 
} 

static IEnumerable<List<object>> PartitionByTypes(List<object> values) 
{ 
    if (values == null) throw new ArgumentNullException("values"); 
    if (values.Count == 0) yield break; 

    Type currentType = GetObjectTypeOrNull(values); 
    List<object> buffer = new List<object>(); 
    foreach (object value in values) 
    { 
     Type valueType = GetObjectTypeOrNull(value); 
     if (valueType != currentType) 
     { 
      currentType = valueType; 
      yield return buffer; 
      buffer = new List<object>(); 
     } 

     currentType = valueType; 
     buffer.Add(value); 
    } 

    if (buffer.Count > 0) 
    { 
     yield return buffer; 
    } 
} 

예 :

List<object> input = new List<object> { "Text1", "Text2", new UndefinedInfo("Undefined1"), new UndefinedInfo("Undefined2"), new UndefinedInfo("Undefined3"), "Text3" }; 
PartitionByTypes(input).ToList(); 

결과 :

{ List<object>(2) { "Text1", "Text2" }, List<object>(3) { [Undefined1], [Undefined2], [Undefined3] }, List<object>(1) { "Text3" } 

다른 예 - 널과 :

List<object> input = new List<object> { null, "Text1", "Text2", null, null, new UndefinedInfo("Undefined1"), null, null, new UndefinedInfo("Undefined2"), new UndefinedInfo("Undefined3"), "Text3" }; 
PartitionByTypes(input).ToList(); 

결과 :

List<object>(1) { null }, List<object>(2) { "Text1", "Text2" }, List<object>(2) { null, null }, List<object>(1) { [Undefined1] }, List<object>(2) { null, null }, List<object>(2) { [Undefined2], [Undefined3] }, List<object>(1) { "Text3" } 
+0

감사합니다 @ alex.b null 예제 – Abhay