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

C# 对集合(非LINQ)的子集合执行布尔和字符串搜索,c#,C#,我希望这个标题有意义 我有一组项目,我想根据一组关键字搜索并选择其中的一个子集,这些关键字必须在项目的任何子项目中至少出现一次。我相信使用LINQ很容易做到这一点,但我在这个项目中使用.NET2.0 假设实现了AllBitsAreSet,下面的代码应该可以实现我想要的功能,但是我想知道我是否缺少一种更简单的替代方法 由于除了循环检查位数组中的所有位(请告诉我是否有!)之外,似乎没有一种很好的方法来检查位数组中的所有位是否都已设置,因此我想知道“更好”的替代方法。不一定CPU效率更高,因为我怀疑下

我希望这个标题有意义

我有一组
项目
,我想根据一组
关键字
搜索并选择其中的一个子集,这些关键字必须在
项目
的任何
子项目
中至少出现一次。我相信使用LINQ很容易做到这一点,但我在这个项目中使用.NET2.0

假设实现了
AllBitsAreSet
,下面的代码应该可以实现我想要的功能,但是我想知道我是否缺少一种更简单的替代方法

由于除了循环检查
位数组
中的所有位(请告诉我是否有!)之外,似乎没有一种很好的方法来检查
位数组中的所有位是否都已设置,因此我想知道“更好”的替代方法。不一定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;
}
公共列表搜索(项[]项,列表关键字)
{
列表结果=新列表();
BitArray标志=新的BitArray(关键字.Count);
foreach(项目中的项目)
{
flags.SetAll(false);
foreach(item.SubItems中的子项子项)
{
for(int i=0;i=0)
flags[i]=true;
}
}
如果(所有位设置(标志))结果。添加(项目);
}
返回结果;
}
您可以使用获取.NET 2.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);
    }
}

我会这样写。当然,这与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;
    }
公共列表搜索(项[]项,列表关键字)
{
列表结果=新列表();
foreach(项目中的项目)
if(包含所有关键字(项目,关键字))
结果:增加(项目);
返回结果;
}
bool包含所有关键字(项目、列表关键字)
{
foreach(关键字中的字符串关键字)
如果(!ContainsKey(item.SubItems,关键字))
返回false;
返回true;
}
bool ContainsKey(IEnumerable子项,字符串键)
{
foreach(子项中的子项)
if(子项.StringValue.Contains(键))
返回true;
返回false;
}

编辑:根据注释将
=
更改为
.Contains()
一个项目可以有多少子项目?内部循环(对于int i=0)对我来说似乎是个问题。如果您提供示例输入/预期输出会更好。您的代码与Blix和Daniel的功能不同。您的代码检查subItem.StringValue和每个关键字之间是否完全匹配。它应该检查子字符串匹配。如果允许精确匹配,则可以进行更好的优化。例如,您可以将关键字作为键存储在字典中(或在.NET的更高版本中使用哈希集),这将给O(1)个查找时间。Luke,是的,这是一个错误,应该是。Contains()而不是==。谢谢你抓住了!我已经编辑了代码。然而,我不同意你关于使用字典/散列的评估。我知道散列查找是O(1),但我不知道如何在这种情况下直接应用它来提高性能。你能提供一个代码示例吗?谢谢你的评论。