查找数组或 XML 中值的频率 (C#)

发布于 2024-07-11 01:34:06 字数 2714 浏览 8 评论 0原文

我有一个 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++;
        } 

感谢您的帮助!

I have an XML feed (which I don't control) and I am trying to figure out how to detect the volume of certain attribute values within the document.

I am also parsing the XML and separating attributes into Arrays (for other functionality)

Here is a sample of my 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>

I want to find the volume nodes based on each att1 value. Att1 value will change. Once I know the frequency of att1 values I need to pull the att2 value of that node.

I need to find the TOP 4 items and pull the values of their attributes.

All of this needs to be done in C# code behind.

If I was using Javascript I would create an associative array and have att1 be the key and the frequency be the value. But since I'm new to c# I don't know how to duplicate this in c#.

So I believe, first I need to find all unique att1 values in the XML. I can do this using:

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

Then I get stuck on how I compare each unique att1 value to the whole document to get the volume stored in a variable or array or whatever data set.

Here is the snippet I ended up using:

        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++;
        } 

Thanks for all your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

长亭外,古道边 2024-07-18 01:34:06

您使用的是.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);

我还没有测试过它,但我认为它应该可以工作...

  • 我们从所有 item 元素开始,
  • 我们按 att1 值对它们进行分组(仍然作为元素)
  • 我们按组的大小降序对组进行排序,因此最大的排在第一个
  • 从每个组中,我们取第一个元素来查找其 att2 值
  • 我们取这些结果中的前四个

Are you using .NET 3.5? (It looks like it based on your code.) If so, I suspect this is pretty easy with LINQ to XML and LINQ to Objects. However, I'm afraid it's not clear from your example what you want. Do all the values with the same att1 also have the same att2? If so, it's something like:

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);

I haven't tested it, but I think it should work...

  • We start off with all the item elements
  • We group them (still as elements) by their att1 value
  • We sort the groups by their size, descending so the biggest one is first
  • From each group we take the first element to find its att2 value
  • We take the top four of these results
脸赞 2024-07-18 01:34:06

如果你有这些值,你应该能够使用 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);
        }

If you have the values, you should be able to use LINQ's 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);
        }
情深缘浅 2024-07-18 01:34:06

您可以使用 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();
        }
    }
}

You can use LINQ/XLINQ to accomplish this. Below is a sample console application I just wrote, so the code might not be optimized but it works.

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();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文