代码之家  ›  专栏  ›  技术社区  ›  Blixt

对集合(非LINQ)的子集合执行布尔和字符串搜索

c#
  •  1
  • Blixt  · 技术社区  · 15 年前

    我希望这个标题有意义。

    我有一套 items 我希望根据一组 keywords 这些信息必须在任何一个列表中至少出现一次 SubItems Item s我相信使用LINQ很容易做到这一点,但我在这个项目中使用.NET2.0。

    AllBitsAreSet 实现了,但我想知道我是否缺少了一种更简单的替代方法?

    BitArray 都设置好了,除了循环它们(请告诉我是否有!),我还想知道“更好”的替代方案。不一定CPU效率更高,因为我怀疑下面的代码对于我正在使用的数据集来说太慢,但是对于代码较少的数据集来说。

    public List<Item> Search(Item[] items, List<string> keywords)
    {
        List<Item> results = new List<Item>();
    
        BitArray flags = new BitArray(keywords.Count);
        foreach (Item item in items)
        {
            flags.SetAll(false);
            foreach (SubItem subItem in item.SubItems)
            {
                for (int i = 0; i < keywords.Count; i++)
                {
                    if (subItem.StringValue.IndexOf(keywords[i]) >= 0)
                        flags[i] = true;
                }
            }
            if (AllBitsAreSet(flags)) results.Add(item);
        }
    
        return results;
    }
    
    2 回复  |  直到 15 年前
        1
  •  3
  •   Daniel Brückner    15 年前

    你可以用 LINQ Bridge 要在.NET2.0上获得LINQ支持,请使用以下LINQ查询。

    items.Where(i =>
        keywords.All(k =>
            i.SubItems.Any(s =>
                s.StringValue.Contains(k))));
    

    如果交换两个内部循环,可以避免使用位集-性能影响取决于子项的数量与关键字的数量。

    foreach (Item item in items)
    {
        Boolean found = false;
    
        foreach (String keyword in keywords)
        {
            found = false;
    
            foreach (SubItem subItem in item.SubItems)
            {
                if (subItem.StringValue.Contains(keyword))
                {
                    found = true;
                    break;
                }
            }
    
            if (!found)
            {
                break;
            }
        }
    
        if (found)
        {
            result.Add(item);
        }
    }
    
        2
  •  0
  •   dss539    15 年前

    我会这样写。当然,这与Daniel的解决方案非常相似,但我相信它更好。

        public List<Item> Search(Item[] items, List<string> keywords)
        {
            List<Item> results = new List<Item>();
            foreach (Item item in items)
                if(ContainsAllKeywords(item, keywords))
                    results.Add(item);
            return results;
        }
    
        bool ContainsAllKeywords(Item item, List<string> keywords)
        {
            foreach (string keyword in keywords)
                if (!ContainsKey(item.SubItems, keyword))
                    return false;
            return true;
        }
    
        bool ContainsKey(IEnumerable<SubItem> subItems, string key)
        {
            foreach (SubItem subItem in subItems)
                if (subItem.StringValue.Contains(key))
                    return true;
            return false;
        }
    

    改变 == .Contains() 根据评论