【问题标题】:How to Check 2 lists for similar items?如何检查 2 个类似项目的列表?
【发布时间】:2021-09-05 17:39:50
【问题描述】:

我有 2 个列表(myItemsanotherItems),我想查看 myItems 上的项目是否在 anotherItems 上?

我目前正在使用 2 个 foreach 循环,但是速度很慢,大约需要 1 分钟。

myItems = IEnumerable<SomeModel>

另一个项目 = IEnumerable<String>

foreach (var item in myItems)
{
    foreach (var subItem in anotherItems)
    {
        var parsed = ParseItem(subItem, item.Id);
        if (parsed.Id != null && parsed.version != null)
        {
            if (item.Id.Equals(parsed.Id, StringComparison.OrdinalIgnoreCase))
            {
                myList.Add(new myModel
                {
                    Name = item.Name,
                    Id = item.Id,
                    Version = parsed.version
                });
                break;
            }
        }
    }
}

而 PareItem 是:

public static (string Id, string version) ParseItem(string line, string Id)
{
    line = Regex.Replace(line, "[ ]{2,}", " ", RegexOptions.IgnoreCase);
    line = Regex.Replace(line, $@".*(?=({Regex.Escape(Id)}))", "", RegexOptions.IgnoreCase);
    var lines = line.Split(" ");
    if (lines.Count() == 2)
    {
        return (Id: lines[0], version: lines[1]);
    }
    return (Id: null, version: null);
}

我怎样才能更快地做到这一点?

【问题讨论】:

  • 你能对你的输入数据做一些假设吗?例如,它们是否已排序?
  • 那里有大量不必要的字符串操作。使用捕获组甚至简单的 IndexOf。显示您的输入数据
  • 此外,您重新解析相同的项目 N 次,其中 N 是外部列表中的项目数 - 这完全是浪费时间。使用任何看起来像 Id 的东西将内部列表解析为 Hashset 并遍历外部列表,询问该集合是否包含该项目
  • 大多数情况下,识别最佳数据表示然后选择正确的算法将比优化我们已经看到的代码带来更大的性能提升。在此之后,parsed.Idparsed.version 当前是字符串标识符。它们是字符串还是表示为字符串的数值? parsed.Id 模式可以是“abc123”还是总是类似于“123”? version 也是如此。
  • @DanielDearlove 你可以在我的问题中看到它

标签: c# list linq foreach


【解决方案1】:

我建议以下解决方案,因为您的问题是您正在为 myItems 的每个迭代提取相同的项目:

  1. anotherItems = IEnumerable<String> 完整解析为IEnumerable<SomeModel>,即使只能设置部分属性(我们知道在任何情况下都可以设置Id)。

  2. 然后您可以使用Intersect

public class SomeModel: IEquatable<SomeModel>
{
    public string Id { get; set; }

    public bool Equals(SomeModel other)
    {
        if (other is null)
            return false;

        return this.Id.Equals(other.Id, StringComparison.OrdinalIgnoreCase);
    }

    public override bool Equals(object obj) => Equals(obj as SomeModel);
    public override int GetHashCode() => (id).GetHashCode();
}

所以我希望你的代码看起来像:

// In this line iterate all items from the second list and extract.
myAnotherItemsList = ExtractSomeModelFromAnotherList(anotherItems);
var mergedList = myList.Intersect(myAnotherItemsList);

【讨论】:

  • 问题是首先我必须使用 ParseItem 方法解析项目,为此我需要项目 ID。
  • 如果无法做出进一步的假设,从原始列表中删除匹配的行可能会加快速度。否则,您需要找到某种方法来提取 ID。是否可以从字符串中获取所有数字并假设 id 是其中之一?这也将提供解决方案。
  • @user16267434 在此处提供解决方案方面,我们实际上仅限于您能够想象的范围,因为您没有发布对实际问题的充分表示;您已经发布了您的解决方案并说“帮助,它很慢,如何让它更快”但我们对您正在处理的数据一无所知,因为您还没有发布它。因此,这是一个 XY 问题,我们只能提取/推断您的能力极限。
  • 如果您发布实际问题(“我有一个像 X 这样的对象列表.. 和一个像这样的字符串列表.. 我怎样才能得到相交?”)然后我们可以提供达到我们能力极限的解决方案,这实际上是您正在寻找的......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-26
  • 2018-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-24
相关资源
最近更新 更多