2011-08-18 3 views
1

Je les dossiers comme celui-ci dans la collection observablePivot une collection observable

 
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 

maintenant je veux nouvelle collection observable comme

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

Comment puis-je obtenir ce type de collection observable?

+2

Qu'est-ce que le résultat soit s'il y avait un '6 .NET 9500 04/08/2011'? –

+2

Il semble que vous essayez de faire pivoter vos données. –

Répondre

1

En supposant que vous avez la structure follwing qui ressemble à votre structure:

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()); 
    } 
} 

et suivants collections observables:

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> 
{ 
} 

Vous pouvez essayer ce code pour résoudre votre problème ou au moins vous mettre sur le chemin à une solution peut-être meilleure:

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); 
} 

J'espère que cela vous aide trouver une solution! :)

+0

Salut Abbas Merci pour votre aide. C'est vraiment une bonne solution pour mon problème. –

1

Il y a quelque temps, j'ai joué avec le pivotement et l'ExpandoObject. Ce n'est certainement pas du code de production.

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; 
} 

puis dans une méthode quelque part

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

En raison de la façon dont mes données est consommé, j'ai besoin les résultats dans un format de table, pas un format d'objet imbriqué. Ainsi, le code ci-dessous produit un pivot à partir d'une liste de données. Il est appelé comme ceci:

// 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} 
      } 
    ); 

Et la méthode d'extension LINQ ressemble à ceci:

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

Cela a bien fonctionné pour moi. Pourrait-il être modifié pour permettre à la valeur pivotée d'être une liste, plutôt qu'une agrégation? Quand j'utilise ce qui suit, je me retrouve avec une représentation de style ToString() de la liste. 'pivot var = people.Pivot ( RowKey => rowKey.managerName ?? "null", \t \t columnKey => columnKey.company ?? "null", \t \t value => value.ToList(), \t \t "gestionnaire" \t \t null \t \t); ' – rdavisau

Questions connexes