2

XML フィード (制御していない) があり、ドキュメント内の特定の属性値のボリュームを検出する方法を見つけようとしています。

また、XML を解析し、属性を配列に分離しています (他の機能用)。

これが私のXMLのサンプルです

<items>
<item att1="ABC123" att2="uID" />
<item att1="ABC345" att2="uID" />
<item att1="ABC123" att2="uID" />
<item att1="ABC678" att2="uID" />
<item att1="ABC123" att2="uID" />
<item att1="XYZ123" att2="uID" />
<item att1="XYZ345" att2="uID" />
<item att1="XYZ678" att2="uID" />
</items>

各att1値に基づいてボリュームノードを見つけたいです。Att1 の値が変わります。att1 値の頻度がわかったら、そのノードの att2 値を取得する必要があります。

上位 4 つの項目を見つけて、それらの属性の値を取得する必要があります。

これらはすべて、C# コード ビハインドで行う必要があります。

Javascript を使用していた場合、連想配列を作成し、att1 をキーに、頻度を値にします。しかし、私はC#が初めてなので、これをC#で複製する方法がわかりません。

したがって、最初に XML 内の一意の att1 値をすべて見つける必要があると思います。私はこれを使用してこれを行うことができます:

IEnumerable<string> uItems = uItemsArray.Distinct();
// Where uItemsArray is a collection of all the att1 values in an array

次に、各一意の att1 値をドキュメント全体と比較して、変数や配列、またはその他のデータ セットに格納されているボリュームを取得する方法に行き詰まります。

最終的に使用したスニペットは次のとおりです。

        XDocument doc = XDocument.Load(@"temp/salesData.xml");
        var topItems = from item in doc.Descendants("item")
                    select new
                    {
                        name = (string)item.Attribute("name"),
                        sku = (string)item.Attribute("sku"),
                        iCat = (string)item.Attribute("iCat"),
                        sTime = (string)item.Attribute("sTime"),
                        price = (string)item.Attribute("price"),
                        desc = (string)item.Attribute("desc")

                    } into node
                    group node by node.sku into grp
                    select new { 
                        sku = grp.Key,
                        name = grp.ElementAt(0).name,
                        iCat = grp.ElementAt(0).iCat,
                        sTime = grp.ElementAt(0).sTime,
                        price = grp.ElementAt(0).price,
                        desc = grp.ElementAt(0).desc,
                        Count = grp.Count() 
                    };

        _topSellers = new SalesDataObject[4];
        int topSellerIndex = 0;
        foreach (var item in topItems.OrderByDescending(x => x.Count).Take(4))
        {
            SalesDataObject topSeller = new SalesDataObject();
            topSeller.iCat = item.iCat;
            topSeller.iName = item.name;
            topSeller.iSku = item.sku;
            topSeller.sTime = Convert.ToDateTime(item.sTime);
            topSeller.iDesc = item.desc;
            topSeller.iPrice = item.price;
            _topSellers.SetValue(topSeller, topSellerIndex);
            topSellerIndex++;
        } 

ご助力いただきありがとうございます!

4

3 に答える 3

4

.NET 3.5 を使用していますか? (あなたのコードに基づいているように見えます。) もしそうなら、これは LINQ to XML と LINQ to Objects を使えばかなり簡単だと思います。ただし、あなたの例からは、あなたが何を望んでいるのかはっきりしないと思います。同じ att1 を持つすべての値は、同じ att2持っていますか? もしそうなら、それは次のようなものです:

var results = (from element in items.Elements("item")
              group element by element.Attribute("att1").Value into grouped
              order by grouped.Count() descending
              select grouped.First().Attribute("att2").Value).Take(4);

私はそれをテストしていませんが、うまくいくはずだと思います...

  • すべてのアイテム要素から始めます
  • それらを att1 値で (要素として) グループ化します
  • グループをサイズで降順に並べ替え、最大のグループが最初になるようにします
  • 各グループから最初の要素を取得してその att2 値を見つけます
  • これらの結果の上位 4 つを取ります
于 2008-12-17T20:47:24.787 に答える
1

値があれば、LINQ の GroupBy を使用できるはずです...

        XDocument doc = XDocument.Parse(xml);
        var query = from item in doc.Descendants("item")
                    select new
                    {
                        att1 = (string)item.Attribute("att1"),
                        att2 = (string)item.Attribute("att2") // if needed
                    } into node
                    group node by node.att1 into grp
                    select new { att1 = grp.Key, Count = grp.Count() };

        foreach (var item in query.OrderByDescending(x=>x.Count).Take(4))
        {
            Console.WriteLine("{0} = {1}", item.att1, item.Count);
        }
于 2008-12-17T20:47:01.120 に答える
1

これを実現するには、LINQ/XLINQ を使用できます。以下は、私が作成したばかりのサンプル コンソール アプリケーションです。コードは最適化されていない可能性がありますが、動作します。

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

namespace FrequencyThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            string data = @"<items>
                            <item att1=""ABC123"" att2=""uID"" />
                            <item att1=""ABC345"" att2=""uID"" />
                            <item att1=""ABC123"" att2=""uID"" />
                            <item att1=""ABC678"" att2=""uID"" />
                            <item att1=""ABC123"" att2=""uID"" />
                            <item att1=""XYZ123"" att2=""uID"" />
                            <item att1=""XYZ345"" att2=""uID"" />
                            <item att1=""XYZ678"" att2=""uID"" />
                            </items>";
            XDocument doc = XDocument.Parse(data);
            var grouping = doc.Root.Elements().GroupBy(item => item.Attribute("att1").Value);

            foreach (var group in grouping)
            {
                var groupArray = group.ToArray();
                Console.WriteLine("Group {0} has {1} element(s).", groupArray[0].Attribute("att1").Value, groupArray.Length);
            }

            Console.ReadKey();
        }
    }
}
于 2008-12-17T20:52:13.153 に答える