C# 当两个字典的值在C中相等时,在列表中合并/添加字典#

C# 当两个字典的值在C中相等时,在列表中合并/添加字典#,c#,dictionary,C#,Dictionary,我想从原始列表字典值(list)中提取一个已处理的字典值列表(list) 原始dict可能包含字符串/数值 例如: Dictionary rawListDict=newdictionary(); 添加(“产品”、“苹果”); 添加(“地区”、“西部”); 添加(“利润”,90); 原始列表: 苹果西90 苹果东10 苹果西80 已处理列表: 苹果西170 苹果东10 考虑一个有相同产品和地区的词典的列表,我想要一个单独的dict,当“产品”和“地区”相同时,添加“利润”。(即)具有类似项的词典

我想从原始列表字典值(
list
)中提取一个已处理的字典值列表(
list

原始dict可能包含字符串/数值

例如:

Dictionary rawListDict=newdictionary();
添加(“产品”、“苹果”);
添加(“地区”、“西部”);
添加(“利润”,90);
原始列表:

苹果西90

苹果东10

苹果西80

已处理列表:

苹果西170

苹果东10

考虑一个有相同产品和地区的词典的列表,我想要一个单独的dict,当“产品”和“地区”相同时,添加“利润”。(即)具有类似项的词典列表,分组为单个词典,没有任何副本

注意:原始列表可以增长到超过30K个条目:-(

我用蛮力技术实现了一个逻辑,它消耗了大量的内存和时间。有没有办法用LINQ风格或者其他方法来减少时间和内存

编辑:我更喜欢字典,因为只有在运行时才知道成员/键的数量。

我实施的代码:

                    //Get fields which could be used for combining values
                    var nonMeasurableFields = report.datagrid_fields.
                        Where(field => field.dataType.Equals(ImFieldDatatype.STRING_VALUE) || field.dataType.Equals(ImFieldDatatype.DATE_VALUE)).
                        Select(field => field.name).ToList();

                    if (nonMeasurableFields != null && nonMeasurableFields.Count > 0)
                    {
                        #region Outer For Loop

                        for (int index = 0; index < processedData.Count; index++)
                        {
                            var baseDict = processedData.ElementAt(index);

                            Dictionary<String, Object> compareDict = null;

                            #region Recursive Loop

                            for (int recursiveIndex = index + 1; recursiveIndex < processedData.Count; recursiveIndex++)
                            {
                                compareDict = processedData.ElementAt(recursiveIndex);

                                int matchesCount = 0;

                                #region comparison logic

                                foreach (var key in nonMeasurableFields)
                                {
                                    var baseDictValue = baseDict[key];
                                    var compareDictValue = compareDict[key];

                                    if (baseDictValue == null && compareDictValue == null)
                                    {
                                        matchesCount++;
                                    }
                                    else
                                    {
                                        if (baseDictValue != null && compareDictValue == null)
                                        {
                                            matchesCount = 0;
                                        }
                                        else if (baseDictValue == null && compareDictValue != null)
                                        {
                                            matchesCount = 0;
                                        }
                                        else if (baseDictValue != null && compareDictValue != null)
                                        {
                                            if (baseDictValue.Equals(compareDictValue))
                                            {
                                                matchesCount++;
                                            }
                                            else
                                            {
                                                matchesCount = 0;
                                            }
                                        }

                                    }
                                }

                                #endregion

                                #region If Match -- Combine

                                if (matchesCount == nonMeasurableFields.Count)
                                {
                                    #region combine logic

                                    // Combine the two dictionary .. 

                                    processedData.Remove(baseDict);
                                    processedData.Remove(compareDict);

                                    // combine the base and compare dict

                                    Dictionary<String, Object> combinedDict = new Dictionary<string, object>();

                                    var keyNeededInDict = baseDict.Keys.ToList();

                                    foreach (var key in keyNeededInDict.ToList())
                                    {
                                        if (nonMeasurableFields.Contains(key))
                                        {
                                            combinedDict.Add(key, baseDict[key]);
                                        }
                                        else
                                        {
                                            Object value = Convert.ToDouble(baseDict[key]) + Convert.ToDouble(compareDict[key]);

                                            combinedDict.Add(key, value);
                                        }
                                    }

                                    processedData.Add(combinedDict);

                                    index = -1; // Resetting the looping index so that the merging works for all values
                                    recursiveIndex = -1; // Ensuring all the values are considered at least once whenever 
                                    // a change is made to the list (i.e merging the dict)
                                    break;
                                    #endregion
                                }
                                else
                                {
                                    // No matches
                                    // continue to next
                                }

                                #endregion
                            }

                            #endregion
                        }

                        #endregion
                    }
//获取可用于组合值的字段
var nonmeasurefields=report.datagrid\u字段。
其中(field=>field.dataType.Equals(ImFieldDatatype.STRING_值)| | field.dataType.Equals(ImFieldDatatype.DATE_值))。
选择(field=>field.name).ToList();
if(nonmeasurefields!=null&&nonmeasurefields.Count>0)
{
#外循环区域
for(int index=0;index                    //Get fields which could be used for combining values
                    var nonMeasurableFields = report.datagrid_fields.
                        Where(field => field.dataType.Equals(ImFieldDatatype.STRING_VALUE) || field.dataType.Equals(ImFieldDatatype.DATE_VALUE)).
                        Select(field => field.name).ToList();

                    if (nonMeasurableFields != null && nonMeasurableFields.Count > 0)
                    {
                        #region Outer For Loop

                        for (int index = 0; index < processedData.Count; index++)
                        {
                            var baseDict = processedData.ElementAt(index);

                            Dictionary<String, Object> compareDict = null;

                            #region Recursive Loop

                            for (int recursiveIndex = index + 1; recursiveIndex < processedData.Count; recursiveIndex++)
                            {
                                compareDict = processedData.ElementAt(recursiveIndex);

                                int matchesCount = 0;

                                #region comparison logic

                                foreach (var key in nonMeasurableFields)
                                {
                                    var baseDictValue = baseDict[key];
                                    var compareDictValue = compareDict[key];

                                    if (baseDictValue == null && compareDictValue == null)
                                    {
                                        matchesCount++;
                                    }
                                    else
                                    {
                                        if (baseDictValue != null && compareDictValue == null)
                                        {
                                            matchesCount = 0;
                                        }
                                        else if (baseDictValue == null && compareDictValue != null)
                                        {
                                            matchesCount = 0;
                                        }
                                        else if (baseDictValue != null && compareDictValue != null)
                                        {
                                            if (baseDictValue.Equals(compareDictValue))
                                            {
                                                matchesCount++;
                                            }
                                            else
                                            {
                                                matchesCount = 0;
                                            }
                                        }

                                    }
                                }

                                #endregion

                                #region If Match -- Combine

                                if (matchesCount == nonMeasurableFields.Count)
                                {
                                    #region combine logic

                                    // Combine the two dictionary .. 

                                    processedData.Remove(baseDict);
                                    processedData.Remove(compareDict);

                                    // combine the base and compare dict

                                    Dictionary<String, Object> combinedDict = new Dictionary<string, object>();

                                    var keyNeededInDict = baseDict.Keys.ToList();

                                    foreach (var key in keyNeededInDict.ToList())
                                    {
                                        if (nonMeasurableFields.Contains(key))
                                        {
                                            combinedDict.Add(key, baseDict[key]);
                                        }
                                        else
                                        {
                                            Object value = Convert.ToDouble(baseDict[key]) + Convert.ToDouble(compareDict[key]);

                                            combinedDict.Add(key, value);
                                        }
                                    }

                                    processedData.Add(combinedDict);

                                    index = -1; // Resetting the looping index so that the merging works for all values
                                    recursiveIndex = -1; // Ensuring all the values are considered at least once whenever 
                                    // a change is made to the list (i.e merging the dict)
                                    break;
                                    #endregion
                                }
                                else
                                {
                                    // No matches
                                    // continue to next
                                }

                                #endregion
                            }

                            #endregion
                        }

                        #endregion
                    }
var lookup = dicList.ToLookup(x => new{
                                    Product = x["Product"], 
                                    Region = x["Region"]});
var condensedDicList = lookup
       .Select(x => new Dictionary<string, object>(){
                         {"Product",x.Key.Product},
                         {"Region",x.Key.Region},
                         {"Profit",x.Sum(d=>(int)d["Profit"])}
        })
       .ToList();
class MyData
{
    public string Product{get;set;}
    public string Region{get;set;}
    public int Profit{get;set;}
}
IEnumerable<IDictionary<string, object>>
IEnumerable<IDictionary<string, object>> Merger(
        IEnumerable<IDictionary<string, object>> source,
        IEnumerable<string> keys,
        IDictionary<string, Func<IEnumerable<object>, object>> aggregators)
{
    var grouped = source.GroupBy(d => string.Join("|", keys.Select(k => d[k])));

    foreach(var g in grouped)
    {
        var result = new Dictionary<string, object>();
        var first = g.First();
        foreach(var key in keys)
        {
            result.Add(key, first[key]);
        }

        foreach(var a in aggregators)
        {
            result.Add(a.Key, a.Value(g.Select(i => i[a.Key])));
        }

        yield return result;
    }
}
var processedDictionaries = Merger(
    rawListDict,
    new[] { "Product", "Region" },
    new Dictionary<string, Func<IEnumerable<object>, object>>
        {
            { "Profit", objects => objects.Cast<int>().Sum() }
        });
var aggregators = new Dictionary<string, Func<IEnumerable<object>, object>>();
aggregators.Add(
     "Profit",
     objects => objects.Cast<string>().Sum(s => double.Parse(s)));
var groupingKeys = new [] { "Product", "Region" };
var aggKey = "Profit";
List<Dictionary<String,Object>> rows = GetRows(); //provided

var results =
from r in rows
let groupingValues = groupingKeys.Select(key => r[key]).ToArray()
let groupingString = string.Join("|", groupingValues) //HACK - you better use an array comparer
let aggValue = Convert.ToInt32(r[aggKey])
group aggValue by groupingString into g
select new { Key = g.Key, Sum = g.Sum() }