List<Dictionary<String,Object>>
生のリストのディクショナリ値 ( ) から、処理されたディクショナリ値のリスト ( ) を抽出したいと考えていますList<Dictionary<String,Object>>
。
Raw dict には文字列/数値が含まれる場合があります
例えば:
Dictionary<String, Object> rawListDict = new Dictionary<String, Object>();
rawListDict.Add("Product","Apple");
rawListDict.Add("Region", "West");
rawListDict.Add("Profit", 90);
生のリスト:
アップル ウエスト 90
アップルイースト 10
アップル ウエスト 80
処理済みリスト:
アップル ウェスト 170
アップルイースト 10
同じ製品と地域を持つ辞書のリストを考えてみましょう。「製品」と「地域」が同じ場合、「利益」を追加して単一の辞書が必要です。(ie) 重複のない単一の辞書としてグループ化された類似の項目を持つ辞書のリスト
注 : raw リストは 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
}
注: どのキー(キーの値)が文字列型と数値型であるかについての情報があります。提供されているサンプルは、デモンストレーションのみを目的としています。キーと値は、実行時にのみ認識されます。文字列の値が等しい場合、2 つの辞書を結合することになっています。結合しながら数値を追加します。
編集 2: リスト内のすべての辞書は同じキーを持ちます。値は破棄されません。同じ値を持つ辞書は結合されます。