从具有多个属性的列表中删除重复值

时间:2017-06-29 21:19:20

标签: c# linq

我有MyClass的列表:

class MyClass
{
    public DateTime? DueDate;
    public string Desc;
    public Decimal Amount;
}

var sample = new List<MyClass>();

这是样本数据的样子:

DueDate     Desc    Amount 
06-29-2015  ABC     100
06-29-2015  DEF     200
01-15-2015  ABC     100
01-15-2015  DEF     200

我希望以这种格式输出

DueDate     Desc    Amount 
06-29-2015  ABC     100
            DEF     200
01-15-2015  ABC     100
            DEF     200

所以基本上我想删除重复的DueDate,但要保持其相邻的Desc&amp; Amount字段值

我试过了,但它也会删除相邻列中的值:

var test = sample.GroupBy(d => d.DueDate).Select(a => a.First()).ToList();

有什么建议吗?

5 个答案:

答案 0 :(得分:0)

var finalData = data
    .GroupBy(d=>d.DueDate)
    .Select(g=>
        new {
            DueDate = g.Key, 
            Values = g.Select(d2=>new{d2.Desc, d2.Amount})})

最终结构将是

finalDate = [
    {
        DueDate:'06-29-1015', 
        Values:[{Desc:"ABC", Amount:100}, {Desc:"DEF", Amount:200}]
    },
    {...}
]

修改: -

var finalData = data
        .GroupBy(d=>d.DueDate)
        .Select(g=>
            new {
                 DueDate = g.Key, 
                 Values = g.Select(d2=>d2)
                })
        .ToDictionary(o=>o.DueDate, o=>o.Values)

答案 1 :(得分:0)

在这里&#34;删除&#34; (设置为null)与DueDate列表中的sample相邻{/ 1}}:

sample.GroupBy(d => d.DueDate).ToList()
    .ForEach(g => g.Skip(1).ToList().ForEach(o => o.DueDate = null));

这是由Group - DueDate完成的,并且对于每个组,Skip - 第一个元素,设置组{{1}中的其余元素}到DueDate

格式输出:

null

结果:

Console.WriteLine("DueDate     Desc    Amount");
foreach (var item in sample)
{
    var dateString = item.DueDate != null
        ? item.DueDate.Value.ToString("MM-dd-yyyy")
        : string.Empty;
    Console.WriteLine(dateString.PadRight(12) + item.Desc + "     " + item.Amount);
}

答案 2 :(得分:-1)

根据您的最新评论,我编辑了我的答案。

据我了解,您的要求是:

  • 按DueDate分组,只允许该组中的第一个拥有 DUEDATE。
  • 结果具有是相同的结构。

如果您想要删除来自组中所有DueDate项的i>0属性,那么您需要使您的属性可以为空:public DateTime? DueDate;。这样,您可以将null值分配给组中的后续项目。

//New list to hold our new items
var outputList = new List<MyClass>();       

//Groups all the items together by DueDate
foreach(var grouping in samples.GroupBy(d => d.DueDate))
{       
    //Iterates through all items in a group (selecting the index as well)
    foreach(var item in grouping.Select((Value, Index) => new { Value, Index }))
    {
        //If this is any item after the first one, we remove the due date
        if(item.Index > 0)
        {
            item.Value.DueDate = null;
        }
        outputList.Add(item.Value);
    }
}

小提琴here

答案 3 :(得分:-1)

我只是希望您按照正确的顺序循环浏览记录。只需从一个空变量开始,并保留其中的最后一个日期。如果下一个值相同,则不要将其绘制出来。如果在下一次迭代中找到另一个日期值,则绘制它并覆盖您的变量以进行进一步的迭代。

是的我知道,Linq和Lambdas都很酷(我也喜欢它们)但在这种情况下它似乎对我来说很合适。

    var last = DateTime.MinValue;
    foreach (var f in sample.OrderBy(x => x.DueDate))
    {
        if (f.DueDate.Equals(last))
            Console.WriteLine("{0}\t{1}\t{2}", "SKIP DATE", f.Desc, f.Amount);
        else
        {
            Console.WriteLine("{0}\t{1}\t{2}", f.DueDate.ToShortDateString(), f.Desc, f.Amount);
            last = f.DueDate;
        }
    }

答案 4 :(得分:-1)

您想要的是数据透视表。这就是它的完成方式:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = new MyClass();
            myClass.Load();
            myClass.CreatePivotTable();

        }
    }
    class MyClass
    {
        public static List<MyClass> samples = new List<MyClass>();

        public DateTime dueDate { get; set; }
        public string desc { get; set; }
        public Decimal amount { get; set; }

        public static DataTable dt = new DataTable();

        public void Load()
        {
            samples = new List<MyClass>() {
                new MyClass() { dueDate = DateTime.Parse("06-29-2015"), desc = "ABC", amount = 100},
                new MyClass() { dueDate = DateTime.Parse("06-29-2015"), desc = "DEF", amount = 200},
                new MyClass() { dueDate = DateTime.Parse("01-15-2015"), desc = "ABC", amount = 100},
                new MyClass() { dueDate = DateTime.Parse("01-15-2015"), desc = "DEF", amount = 100}
            };

        }
        public void CreatePivotTable()
        {
            string[] uniqueDescription = samples.Select(x => x.desc).Distinct().ToArray();

            dt.Columns.Add("Due Date", typeof(DateTime));
            foreach (string desc in uniqueDescription)
            {
                dt.Columns.Add(desc, typeof(decimal));
            }

            var groups = samples.GroupBy(x => x.dueDate);

            foreach(var group in groups)
            {
                DataRow newRow = dt.Rows.Add();
                newRow["Due Date"] = group.Key;

                foreach (string col in uniqueDescription)
                {
                    newRow[col] = group.Where(x => x.desc == col).Sum(x => x.amount);
                }

            }

        }

    }
}