【问题标题】:LINQ c# unique element in collectionLINQ c#集合中的唯一元素
【发布时间】:2011-11-08 00:07:14
【问题描述】:

我有一个方法应该检查集合中是否有一个元素对某些谓词(作为 Func 给出)成立。

public bool ExistsUnique(Func<T, bool> p)
    {
        var tempCol = from i in MyCollection where p(i) select i;  
        return (tempCol.Count() == 1);
    }

这样做的问题是,当第二个元素也适用于谓词时 找到(例如,集合中存在两个相同的字符串)计数仍然是 1。这意味着它要么覆盖第一个元素,要么永远不会添加第二个元素,因为它已经存在。

关于如何解决此方法的任何想法? 谢谢 /彼得

【问题讨论】:

标签: c# linq collections predicate


【解决方案1】:

你可以像这样使用LINQ提供的Single()方法:

public bool ExistsUnique(Func<T, bool> p)
{
    try
    {
        var temp = myCollection.Single(x => p(x));
    }
    catch(Exception e)
    {
        // log exception
        return false;
    }

    return true;
}

"返回序列中唯一满足指定条件的元素,并抛出 如果存在多个此类元素,则会出现异常。”

来自http://msdn.microsoft.com/en-us/library/bb535118.aspx

编辑

为避免抛出异常,您还可以使用SingleOrDefault() 方法:

public bool ExistsUnique(Func<T, bool> p)
{
    return myCollection.SingleOrDefault(x => p(x)) != null;
}

【讨论】:

  • 这是个好主意!我试过了,但我仍然遇到同样的问题,即使我尝试添加两个相同的字符串,它也会返回 true。
  • 在不必要的时候抛出异常会很慢,当有简单的方法无异常地做同样的事情时,可能要小心这种技术。
  • 添加了一个无异常的选项,但也将异常留在了那里。我认为两者都是可行的选择,具体取决于所需的结果。
  • @shuniar 我不同意,但删除了 -1。顺便说一句,在回复时,如果您在评论中加上他们的名字,人们会更快地知道
【解决方案2】:

肯定有其他问题。我怀疑你的谓词。例如,这将返回计数 2,正如预期的那样:

        List<string> MyCollection = new List<string>()
        {
            "hello",
            "hello"
        };
        var tempCol = from i in MyCollection where i == "hello" select i;
        int count = tempCol.Count();

我怀疑这也是你所说的方式。以下作品(返回false):

    static List<string> MyCollection = new List<string>()
        {
            "hello",
            "hello"
        };

    static bool ExistsUnique(Func<string, bool> p)
    {
        var tempCol = from i in MyCollection where p(i) select i;
        return tempCol.Count() == 1;
    }

    static void DoIt()
    {
        bool isUnique = ExistsUnique((s) => s.Equals("hello"));
        Console.WriteLine(isUnique);
    }

【讨论】:

  • 我认为你可能是对的。虽然我认为谓词 my_set.ExistsUnique(s => s.Equals("Hello")) 很好。我在我的 Exists 方法中使用了完全相同的方法(只是检查至少一个元素是否成立,这有效)。会不会是我写p(i)的方式?
  • @PNS:查看我的更新答案。我认为问题不在于您的称呼方式。
  • 现在我真的很困惑,与您的方法和我自己的方法的唯一区别是您的 ExistsUnique 方法采用 string,bool 而我的采用 T,bool 但它仍然应该工作。对吗?
【解决方案3】:

您确定tempCol 已完全循环通过MyCollectionCount() 是强制完成循环的方法还是惰性的?

例如tempCol.ToList().Count 是否给出正确的结果?

【讨论】:

  • 我试着说 p(i) || !p(i) 它在集合中添加了所有元素一次(没有重复),只是为了检查它是否真的遍历了它所做的所有元素。
【解决方案4】:

这个实现可以让你不必真正枚举整个集合,这样可以节省一些执行时间。

public bool ExistsUnique(Func<T, bool> p)
{
    return MyCollection.Where(i => p(i)).Take(2).Count() == 1;
}

Take(2)Count 限制为仅枚举符合条件的前两个。

【讨论】:

    猜你喜欢
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 1970-01-01
    相关资源
    最近更新 更多