毎朝別々のXMLファイルで受信される大量のデータがあります。XML内のオブジェクトを組み合わせて、それらからレポートを生成する必要があります。私はこの問題に最適な解決策を使用することを探しています。
実証するために、次の例を作成しました。
2つのXMLファイルがあります。
1つ目は、言語とそれらが話されている国のリストです。2つ目は、製品とそれらが販売されている国のリストです。私が生成するレポートは、製品名とそれに続くパッケージの言語です。
XML1:
<?xml version="1.0" encoding="utf-8"?>
<languages>
<language>
<name>English</name>
<country>8</country>
<country>9</country>
<country>3</country>
<country>11</country>
<country>12</country>
</language>
<language>
<name>French</name>
<country>3</country>
<country>6</country>
<country>7</country>
<country>13</country>
</language>
<language>
<name>Spanish</name>
<country>1</country>
<country>2</country>
<country>3</country>
</language>
</languages>
XML2:
<?xml version="1.0" encoding="utf-8"?>
<products>
<product>
<name>Screws</name>
<country>3</country>
<country>12</country>
<country>29</country>
</product>
<product>
<name>Hammers</name>
<country>1</country>
<country>13</country>
</product>
<product>
<name>Ladders</name>
<country>12</country>
<country>39</country>
<country>56</country>
</product>
<product>
<name>Wrenches</name>
<country>8</country>
<country>13</country>
<country>456</country>
</product>
<product>
<name>Levels</name>
<country>19</country>
<country>18</country>
<country>17</country>
</product>
</products>
サンプルプログラム出力:
Screws -> English, French, Spanish
Wrenches -> English, French
Hammer - > French, Spanish
Ladders-> English
現在、DataSetに逆シリアル化し、linqを使用してデータセット間で結合し、必要なレポート文字列を生成しています。(以下に表示-ファイルの名前をコマンドライン引数として渡します)。
public static List<String> XMLCombine(String[] args)
{
var output = new List<String>();
var dataSets = new List<DataSet>();
//Load each of the Documents specified in the args
foreach (var s in args)
{
var path = Environment.CurrentDirectory + "\\" + s;
var tempDS = new DataSet();
try
{
tempDS.ReadXml(path);
}
catch (Exception ex)
{
//Custom Logging + Error Reporting
return null;
}
dataSets.Add(tempDS);
}
//determine order of files submitted
var productIndex = dataSets[0].DataSetName == "products" ? 0:1;
var languageIndex = dataSets[0].DataSetName == "products" ? 1:0;
var joined = from tProducts in dataSets[productIndex].Tables["product"].AsEnumerable()
join tProductCountries in dataSets[productIndex].Tables["country"].AsEnumerable() on (int)tProducts["product_id"] equals (int)tProductCountries["product_id"]
join tLanguageCountries in dataSets[languageIndex].Tables["country"].AsEnumerable() on (String)tProductCountries["country_text"] equals (String)tLanguageCountries["country_text"]
join tLanguages in dataSets[languageIndex].Tables["language"].AsEnumerable() on (int)tLanguageCountries["language_Id"] equals (int)tLanguages["language_Id"]
select new
{
Language = tLanguages["name"].ToString(),
Product = tProducts["name"].ToString()
};
var listOfProducts = joined.OrderByDescending(_ => _.Product).Select(_ => _.Product).Distinct().ToList();
foreach (var e in listOfProducts)
{
var e1 = e;
var languages = joined.Where(_ => _.Product == e1).Select(_ => _.Language).Distinct().ToList();
languages.Sort();
//Custom simple Array to text method
output.Add(String.Format("{0} {1}", e, ArrayToText(languages)));
}
return output;
}
これは問題なく機能しますが、この問題にはもっと最適な解決策が必要であることを私は知っています(特に、XMLファイルが実際に巨大な場合)。誰かが別のアプローチ(linq以外)の経験や、現在のアプローチを最適化することで私を最良の解決策に近づけるためのアドバイスを持っていますか?
よろしくお願いします。
ソリューション 提案されたソリューションの実装:辞書を使用したCasperahのアプローチは、312msでデータセットを処理しました。Linq Lookupを使用したyamenのアプローチは、452msでデータセットを処理しました。