在Dictionary属性

时间:2017-08-30 13:49:59

标签: c# linq dictionary group-by

我有一个名为FileRecordDto的DTO,其属性是字符串字典。该字典代表一个交易记录。值都是字符串,键是列名:

public class FileRecordDto
{
    public IDictionary<string, string> Fields { get; internal set; }
        = new Dictionary<string, string>();
}

我还有一个枚举包装类来表示列名

public class FieldName
{
    public enum CRFS
    {
        Amount,
        ActionDate,
        ContractReference,
        CycleDate,
    }
}

给定FileRecordDtos的输入列表,我需要根据四个字段按唯一记录进行分组。我在StackOverflow上找到了一个standard方法来处理这个问题,但是在检查一个字符串数组时它似乎会中断:

var filteredRecords = originalRecords.GroupBy(x => new string[]
{
    x.Fields[nameof(FieldName.CRFS.ContractReference)],
    x.Fields[nameof(FieldName.CRFS.ActionDate)],
    x.Fields[nameof(FieldName.CRFS.Amount)],
    x.Fields[nameof(FieldName.CRFS.CycleDate)]
});

return filteredRecords.Select(y => y.First()).ToList();

运行时的IntelliSense检查显示两个不同记录的字符串数组看起来可能相同,但它们被视为不同的值。

我做错了什么?

3 个答案:

答案 0 :(得分:2)

使用anonymous type

@Override
public void onBackPressed() {
   Intent i = new Intent(this, MainActivity.class);
   i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
   i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(i);
}

答案 1 :(得分:0)

您需要定义自定义IEqualityComparer<TKey>以按值而不是按引用比较数组。 这个的实现将是:

public class ArrayEqualityComparer<T> : IEqualityComparer<T[]>
{
    public bool Equals(T[] x, T[] y)
    {
        return x.SequenceEqual(y);
    }


    public int GetHashCode(T[] array)
    {
        int hc = array.Length;
        for (int i = 0; i < array.Length; ++i)
        {
            hc = unchecked(hc * 314159 + array[i].GetHashCode());
        }
        return hc;
    }
}

用法:

var filteredRecords = originalRecords.GroupBy(new string[]
{
    x.Fields[nameof(FieldName.CRFS.ContractReference)],
    x.Fields[nameof(FieldName.CRFS.ActionDate)],
    x.Fields[nameof(FieldName.CRFS.Amount)],
    x.Fields[nameof(FieldName.CRFS.CycleDate)]
}, new ArrayEqualityComparer<string>());

如果字段数已修复,则可以使用匿名对象:

var filteredRecords = originalRecords.GroupBy(x => new 
{
    ContractReference = x.Fields[nameof(FieldName.CRFS.ContractReference)],
    ActionDate = x.Fields[nameof(FieldName.CRFS.ActionDate)],
    Amount = x.Fields[nameof(FieldName.CRFS.Amount)],
    CycleDate = x.Fields[nameof(FieldName.CRFS.CycleDate)]
}); 

答案 2 :(得分:-1)

正如@mjwills所提到的,当我在没有new部分的情况下尝试string[]时,我只是缺少属性名称。所以这有效:

var filteredRecords = originalRecords.GroupBy(x => new
{
    a = x.Fields[nameof(FieldName.CRFS.ContractReference)],
    b = x.Fields[nameof(FieldName.CRFS.ActionDate)],
    c = x.Fields[nameof(FieldName.CRFS.Amount)],
    d = x.Fields[nameof(FieldName.CRFS.CycleDate)]
});

return filteredRecords.Select(y => y.First()).ToList();

为了完整起见,以下修复了我的问题,两个看似相似的字符串数组被视为唯一;我认为这是比较字符串指针而不是值。将GetHashCode值相加就像魅力一样:

var filteredRecords = originalRecords.GroupBy(x =>                  
    x.Fields[nameof(FieldName.CRFS.ContractReference)].GetHashCode()
    + x.Fields[nameof(FieldName.CRFS.ActionDate)].GetHashCode()
    + x.Fields[nameof(FieldName.CRFS.Amount)].GetHashCode()
    + x.Fields[nameof(FieldName.CRFS.CycleDate)].GetHashCode());

return filteredRecords.Select(y => y.First()).ToList();