2011-08-18 4 views
1

내가 관찰 컬렉션에서이 같은 기록이피벗 관측 수집

 
ID Department salary joingdate 
1 .NET 5000 04/08/2011 
2 .NET 6000 04/07/2011 
3 JAVA 7000 04/08/2011 
4 JAVA 8000 04/07/2011 
5 .NET 9000 04/06/2011 

가 지금은

 
Joingdate .NET(Salary) JAVA(Salary) 
04/08/2011 5000  7000 
04/07/2011 6000  8000 
04/06/2011 9000  NULL 

같은 새로운 관찰 컬렉션을 어떻게 관찰이 유형의 컬렉션을 얻을 것입니다 싶어?

+2

앞에'6 .NET 9500 04/08/2011'이 있다면 그 결과는 무엇을 할 것인가? –

+2

데이터를 피벗하려고하는 것 같습니다. –

답변

1

당신이 당신의 구조와 유사한 구조 follwing을 한 가정 : 당신은 당신의 문제를 해결하기 위해이 코드를 시도하거나 적어도 방법에 당신을 얻을 수

public class Data1List : ObservableCollection<Data1> 
{ 
    public Data1List() 
    { 
     Add(new Data1{ Id = 1, Dep = ".NET", Sal = 5000, JoinDate = "04/08/2011"}); 
     Add(new Data1{ Id = 2, Dep = ".NET", Sal = 6000, JoinDate = "04/07/2011"}); 
     Add(new Data1{ Id = 3, Dep = "JAVA", Sal = 7000, JoinDate = "04/08/2011"}); 
     Add(new Data1{ Id = 4, Dep = "JAVA", Sal = 8000, JoinDate = "04/07/2011"}); 
     Add(new Data1{ Id = 5, Dep = ".NET", Sal = 9000, JoinDate = "04/06/2011"}); 
    } 
} 

public class Data2List : ObservableCollection<Data2> 
{ 
} 

:

public class Data1 
{ 
    public int Id { get; set; } 
    public String Dep { get; set; } 
    public int Sal { get; set; } 
    public String JoinDate { get; set; } 
} 

public class Data2 
{ 
    public Data2() 
    { 
     Sal = new List<int>(); 
    } 

    public List<int> Sal { get; set; } 
    public String JoinDate { get; set; } 

    public override string ToString() 
    { 
     return Sal.Aggregate(JoinDate, (current, s) => current + s.ToString()); 
    } 
} 

그리고 다음과 같은 관찰 컬렉션 어쩌면 더 나은 해결책이 될 수 있습니다.

var l1 = new Data1List(); 
var l2 = new Data2List(); 

foreach (var items in l1.GroupBy(d => d.JoinDate)) 
{ 
    var d2 = new Data2 { JoinDate = items.Key }; 
    foreach (var item in items) 
     d2.Sal.Add(item.Sal); 
    l2.Add(d2); 
} 

해결책을 제시하십시오! :)

+0

안녕하세요 압바스 당신의 도움에 감사드립니다. 이것은 내 문제에 대한 정말 좋은 해결책이다. –

1

얼마 전 나는 피벗과 ExpandoObject를 가지고 놀았습니다. 확실히 생산 코드가 아닙니다.

public static dynamic pivot(IEnumerable<Employee> rows) 
{ 
    IDictionary<string, Object> expando = new ExpandoObject(); 
    expando["Joindate"] = rows.First().Joindate; 
    foreach (var row in rows) 
    { 
     expando[row.Department] = row.Salary; 
    } 
    return (dynamic)expando; 
} 

다음 어딘가에

var employees = new ObservableCollection<Employee>() { 
    new Employee() {ID=1, Department="NET", Salary=5000, Joindate=new DateTime(2011,04,08)}, 
    new Employee() {ID=2, Department="NET", Salary=6000, Joindate=new DateTime(2011,04,07)}, 
    new Employee() {ID=3, Department="JAVA", Salary=7000, Joindate=new DateTime(2011,04,08)}, 
    new Employee() {ID=4, Department="JAVA", Salary=8000, Joindate=new DateTime(2011,04,07)}, 
    new Employee() {ID=5, Department="NET", Salary=9000, Joindate=new DateTime(2011,04,06)} 
}; 

var distinctDates = employees.Select(j => j.Joindate).Distinct().OrderByDescending(d => d); 

var salaryByDepartmentAndJoindate = distinctDates.Select(d => pivot(employees.Where(jd => jd.Joindate == d))); 

var result = new ObservableCollection<dynamic>(salaryByDepartmentAndJoindate); 
1

때문에 내 데이터가 소비하는 방법을 몇 가지 방법으로, 나는 테이블 형식이 아닌 중첩 된 객체 형식으로 결과를 필요로했다. 따라서 아래 코드는 데이터 목록에서 피벗을 생성합니다.

// generate a pivot table 
    var pivot = linqQueryResults.Pivot(
     rowKey => rowKey.DepartmentName, 
     columnKey => columnKey.JoiningDate, 
     value => value.Sum(emp => emp.Salary), 
     "Department", 
     new Dictionary<string, Func<GetComplianceForClientCurriculums_Result, object>>() 
      { 
       {"DepartmentCode", extraRow => extraRow.DepartmentCode}, 
       {"DepartmentManager", extraRow => extraRow.DeptManager} 
      } 
    ); 

그리고 LINQ 확장 방법은 다음과 같습니다 : 그것은 다음과 같이이라고

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

namespace MyApplication.Extensions 
{ 

    public static class LinqExtenions 
    { 
     /// <summary> 
     ///  Groups the elements of a sequence according to a specified firstKey selector 
     ///  function and rotates the unique values from the secondKey selector function into 
     ///  multiple values in the output, and performs aggregations. 
     /// </summary> 
     /// <param name="source">The data source for the pivot</param> 
     /// <param name="rowKeySelector">A function to derive the key for the rows</param> 
     /// <param name="columnKeySelector">A function to derive the key for the columns</param> 
     /// <param name="valueSelector">A function to calculate the contents of the intersection element. Usually this is an aggreation function</param> 
     /// <param name="firstColumnName">The label to give the first column (row title)</param> 
     /// <param name="additionalHeaderSelectors">An optional dictionary of additional rows to use as headers. Typically, this data should be consistent with the row selector since only the first match is taken.</param> 
     /// <returns>A datatable pivoted from the IEnumerable source.</returns> 
     /// <remarks> 
     /// Based on concepts from this article: http://www.extensionmethod.net/Details.aspx?ID=147 
     /// </remarks> 
     public static DataTable Pivot<TSource, TRowKey, TColumnKey, TValue>(this IEnumerable<TSource> source, Func<TSource, TRowKey> rowKeySelector, Func<TSource, TColumnKey> columnKeySelector, Func<IEnumerable<TSource>, TValue> valueSelector, string firstColumnName = "", IDictionary<string, Func<TSource, object>> additionalHeaderSelectors = null) 
     { 
      var result = new DataTable(); 

      // determine what columns the datatable needs and build out it's schema 
      result.Columns.Add(new DataColumn(firstColumnName)); 
      var columnNames = source.ToLookup(columnKeySelector); 
      foreach (var columnName in columnNames) 
      { 
       var newColumn = new DataColumn(columnName.Key.ToString()); 
       result.Columns.Add(newColumn); 
      } 

      // if we have a 2nd header row, add it 
      if (additionalHeaderSelectors != null) 
      { 
       foreach (var additionalHeaderSelector in additionalHeaderSelectors) 
       { 
        var newRow = result.NewRow(); 

        newRow[firstColumnName] = additionalHeaderSelector.Key; 

        foreach (var columnName in columnNames) 
        { 
         newRow[columnName.Key.ToString()] = additionalHeaderSelector.Value(columnName.FirstOrDefault()); 
        } 

        result.Rows.Add(newRow); 
       } 
      } 


      // build value rows 
      var rows = source.ToLookup(rowKeySelector); 
      foreach (var row in rows) 
      { 
       var newRow = result.NewRow(); 

       // put the key into the first column 
       newRow[firstColumnName] = row.Key.ToString(); 

       // get the values for each additional column 
       var columns = row.ToLookup(columnKeySelector); 
       foreach (var column in columns) 
       { 
        newRow[column.Key.ToString()] = valueSelector(column); 
       } 

       result.Rows.Add(newRow); 
      } 

      return result; 
     } 
    } 
} 
+0

이것은 나를 위해 잘 작동했습니다. 피벗 된 값을 집계가 아닌 목록으로 허용하도록 수정 될 수 있습니까? 아래를 사용할 때 목록의 ToString() 스타일 표현으로 끝납니다. 'VAR 피봇 = people.Pivot ( rowKey => rowKey.managerName ??, "NULL" \t \t columnKey => columnKey.company ?? "NULL" \t \t 값 => value.ToList() \t \t "관리자", \t \t null \t \t) – rdavisau