【问题标题】:How to search a item from List<object>如何从 List<object> 中搜索项目
【发布时间】:2014-11-14 09:46:38
【问题描述】:

我有兴趣从 List 中查找值。我正在研究组件列表。下面是我的对象结构。

Public Class Component
{
   public string Type {get; set;}
   public List<ComponentDetails> Details {get; set;}
}

& 我的 ComponentDetails 结构是

Public Class ComponentDetails
{
  public string Filename {get; set;}
  public string Size {get; set;}
  public DateTime Date {get; set;}
}

我有两个对象,即 Source 和 Destination(类型为 List&lt;Component&gt;)。我需要从源获取第一个项目并从目的地找到详细信息。目标是根据 Size 和 createdDate 找出源与目标之间的任何差异。

换句话说,使用循环,从 Source 中获取第一项(即 Name)并获取 Destination 中的值。

这里的问题是,如何迭代目标项以查找给定的文件名详细信息。

请帮忙!

请注意:目的地可以是 n 个数字。我需要获取源项目并从所有目的地获取详细信息。

代码片段:

    protected void btnGetComparisionResult_Click(object sender, EventArgs e)
    {
        List<Components> sourceComponents = GetSourceComponents();
        List<Components> destinationComponent = GetDestinationComponents();

        foreach (var pitem in sourceComponents) // ParentItem - Component Class
        {
            foreach (var citem in pitem.ComponentDetails) //Child Item - ComponentDetail Class
            {
        //here I need to pass "citem.Name" as input and 
                    //need to get the details from Detination.

                    //IF IT MATCHES, I NEED TO CREATE A REPORT. 
                    //ComponentName  SrcSize    SrcDate   DestSize   DestDate.
            }
        }
    }

最后,如果源的大小和日期时间更大,我们需要采取必要的措施。

【问题讨论】:

  • 你的代码在哪里?你卡在哪一部分了?
  • 嗨 L.B,当我从 Destination 获取详细信息时我被卡住了(考虑现在我只有一个 Destination Object)。使用 foreach 循环,我从源中获取了第一个元素,并尝试从 Destinaion 获取对象
  • BlueMoon,显示您的代码
  • 他的意思是,编辑您的问题以包含代码示例,显示您到目前为止所拥有的内容。
  • 添加了我的代码 sn-p。

标签: c# linq for-loop


【解决方案1】:

我无法测试我的答案,因为我没有任何数据,但这应该可以。您可以对提取的信息做任何您想做的事情,而不是打印它。

    List<Component> Source = new List<Component>();
    List<Component> Destination = new List<Component>();

    foreach (Component c in Destination)
    {
        Console.WriteLine(c.Details);
    }

【讨论】:

  • 嗨,我更喜欢 Linq 查询,因为源和目标中的项目数量都将超过 25k。因此,不要为单个 SourceItem 循环所有 25K 记录,而是会导致性能问题。
  • @BlueMoon:你认为 linq 会做什么?这不是魔术。它也必须遍历集合。
  • 你应该看看this link
  • @BlueMoon 我可能错了,但在这些情况下,foreach 循环可以说更快,因为无论如何 Linq 都会做同样的事情。 Linq 只允许使用更简单的语法。
【解决方案2】:

您得到两个Component 列表,其中一个包含Type 属性,另一个包含Details 属性?无论如何,听起来你应该重构这个设计。如果这不可能,请尝试使用 IEnumerables linq 方法,例如:

list1.ForEach(x => list2.First(v => v.Name == x.Name));

编辑

好的,您添加了代码,现在更清楚了。真的,这听起来好像你根本不需要Component 类。 你应该重构 IMO。像这样的:

protected void btnGetComparisionResult_Click(object sender, EventArgs e) {
    Dictionary<string, ComponentDetails> sourceComponentsDetails //key is component name
      = GetSourceComponentDetails();
    Dictionary<string, ComponentDetails> destinationComponentDetails //key is component name
      = GetDestinationComponentsDetials();

    foreach(string name in sourceComponentsDetails.Keys) {
        if(destinationComponentDetails.Contains(name)) {
            // create report here with name, sourceComponentsDetails[name].Size,
            // sourceComponentsDetails[name].Date, destinationComponentDetails[name].Size
            // and destinationComponentDetails[name].Date
        }
    }

如果你不能重构,或者不想重构,linq 是简洁的并且与foreach 一样高效。我看到有几个人回答了 linq 示例,所以你应该看看。

【讨论】:

  • 我会试试这个,BTW Type 只不过是 ComponentType。它是String类型的。
【解决方案3】:

类似这样的:

    var matched = from s in source
        join d in destination on s.Type equals d.Type
        select d;

join 你的sourcedestination 匹配Type 属性并从destination 中选择对象

如果您需要源对象和目标对象(以便比较详细信息),您可以:

    var matched = from s in source
        join d in destination on s.Type equals d.Type
        select new { s, d };

如果您想让它成为左连接(因此即使destination 中没有匹配项,source 中的所有记录也会返回),那么您可以这样做:

    var matched = from s in source
        join d in destination on s.Type equals d.Type into tmp
        from t in tmp.DefaultIfEmpty()
        select new { s, d = t };

这是一个例子:https://dotnetfiddle.net/J7iDmJ

【讨论】:

  • 嗨,马特,源和目标都具有相同的值集。说Type A,Type B,Type C。所以与Type匹配可以帮助我们过滤从25K到7-8K的记录。
  • @BlueMoon:好的……这就是它实际上在做什么。它按类型匹配它们。这就是s.Type equals d.Type 的意思。
  • 是的,这可以帮助我过滤记录,但我想要的是单个文件的详细信息,例如大小、来自源和目标的日期。我在我的问题中添加了代码 sn-p。希望这能帮助你理解我的问题。
  • @BlueMoon:是的,他们就在sd 那里(随意选择更好的名称)。你的问题没有任何意义。您正在循环通过source 中的Details,但没有迹象表明您将如何将它们与destination 中的Details 匹配。我猜只是通过索引?在这种情况下,只需一个简单的 for 循环即可。
  • 我要问的是,迭代Destination 的更好方法是什么?我们需要通过传递源名称从Destination 搜索整个项目。我正在寻求专家的帮助如何处理这个问题?
【解决方案4】:

这是一种用于搜索所有项目的“老派”循环方法:

public static void GenericTester()
{
    var source = GetSourceComponents();
    var destination = GetDestinationComponents();

    // Go through each source item
    foreach (var srcItem in source)
    {
        // And for each source, look through each destination item
        foreach (var dstItem in destination)
        {
            // See if the destination has the same Type as the source
            if (srcItem.Type == dstItem.Type)
            {
                // source and destination are the same type, so examine file details
                foreach (var srcDetail in srcItem.Details)
                {
                    foreach (var dstDetail in dstItem.Details)
                    {
                        // See if destination detail has a filename that matches the source detail filename
                        if (srcDetail.Filename == dstDetail.Filename)
                        {
                            // Do some comparison between the source.ComponentDetail 
                            // and destination.ComponentDetail here:
                            // . . .

                            break;
                        }
                    }
                }

                break;
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-11
    • 2015-08-02
    • 2019-04-21
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    相关资源
    最近更新 更多