C#使用linq返回对象的通用列表

时间:2011-11-02 10:05:22

标签: c# linq filter generic-list

我有一个通用列表,如下所示:

List<PicInfo> pi = new List<PicInfo>();

PicInfo是一个如下所示的类:

[ProtoContract]
public class PicInfo
{
        [ProtoMember(1)]
        public string fileName { get; set; }
        [ProtoMember(2)]
        public string completeFileName { get; set; }
        [ProtoMember(3)]
        public string filePath { get; set; }
        [ProtoMember(4)]
        public byte[] hashValue { get; set; }

        public PicInfo() { } 
}

我要做的是:

  • 首先,使用重复的文件名过滤列表并返回重复的对象;
  • than,使用重复的哈希值过滤返回的列表;

我只能找到有关如何执行此操作以返回匿名类型的示例。但我需要它作为通用列表。

如果有人可以帮助我,我会很感激。还请解释一下你的代码。这对我来说是一个学习过程。

提前感谢!

[编辑]

通用列表包含对象列表。这些物品是图片。每张图片都有一个文件名,哈希值(以及一些此时无关的数据)。某些图片具有相同的名称(重复的文件名)。我想从这个通用列表'pi'中获取重复文件名的列表。

但这些图片也有哈希值。从相同的文件名中,我想要另一个具有相同哈希值的相同文件名列表。

[/编辑]

3 个答案:

答案 0 :(得分:3)

这样的事情应该有效。是否是最好的方法,我不确定。它效率不高,因为对于每个元素,您再次遍历列表以获得计数。

List<PicInfo> pi = new List<PicInfo>();
IEnumerable<PicInfo> filt = pi.Where(x=>pi.Count(z=>z.FileName==x.FileName)>1);

我希望代码不是太复杂,不需要解释。无论如何,我总是认为最好自己解决这个问题,但如果有任何问题令人困惑,那么就问问我会解释。

如果您希望第二个过滤器针对相同的文件名进行过滤,并且相同的哈希值是重复的,那么您只需要在Count中扩展lambda来检查哈希值。

显然,如果你最后只想要文件名,那么只需要Select就可以获得这些文件名的可枚举列表,如果你只想让它们出现,可能需要Distinct一次。

NB。手写的代码所以请原谅错别字。可能无法第一次编译等; - )

编辑解释代码 - 剧透! ; - )

在英语中,我们想要做的是以下内容:

  

对于列表中的每个项目,我们要选择它,当且仅当列表中有多个具有相同文件名的项目时才会选择。

将其分解为遍历列表并根据我们使用Where方法的条件选择内容。我们where方法的条件是

  

列表中有多个具有相同文件名的项目

为此,我们显然需要对列表进行计数,因此我们使用pi.Count。但是我们有一个条件,我们只计算文件名是否匹配,所以我们传入一个表达式告诉它只计算那些东西。

表达式将对列表中的每个项目起作用,如果我们想要计算它,则返回true,如果我们不想,则返回false。

我们感兴趣的文件名是x,我们正在过滤的项目。所以我们想要计算有多少项的文件名与x.FileName相同。因此我们的表达式为z=>z.FileName==x.FileName。所以z是我们在这个表达式中的变量,并且当我们遍历z时,此上下文中的x.FileName是不变的。

我们当然将我们的标准放在&gt; 1中以获得我们想要的布尔值。

如果您在考虑文件名和哈希值时想要那些重复项,那么您可以将计数中的部分展开为z=>z.FileName==x.FileName && z.hashValue==x.hashValue

所以你在两个值上得到不同的最终代码是:

列出pi = new List();
List filt = pi.Where(x =&gt; pi.Count(z =&gt; z.FileName == x.FileName&amp;&amp; z.hashValue == x.hashValue)&gt; 1).ToList( );

如果你想要那些在考虑文件名和hashvalue时重复的那些,那么你将扩展Count中的部分以比较hashValue。由于这是一个数组,因此您需要使用SequenceEqual方法按值比较它们。

因此,在两个值上获得不同的最终代码将是:

List<PicInfo> pi = new List<PicInfo>();
List<PicInfo> filt = pi.Where(x=>pi.Count(z=>z.FileName==x.FileName && z.hashValue.SequenceEqual(x.hashValue))>1).ToList();

请注意,我没有创建中间列表,只是直接从原始列表中删除。您可以从中间列表中进行操作,但如果从原始列表到过滤列表,则代码将大致相同。

答案 1 :(得分:1)

我认为,你必须使用SequenceEqual方法来寻找dublicate (http://msdn.microsoft.com/ru-ru/library/bb348567.aspx)。 对于过滤器使用

答案 2 :(得分:0)

        var p = pi.GroupBy(rs => rs.fileName) // group by name
            .Where(rs => rs.Count() > 1) // find group whose count greater than 1
            .Select(rs => rs.First()) // select 1st element from each group
            .GroupBy(rs => rs.hashValue) // now group by hash value
            .Where(rs => rs.Count() > 1) // find group has multiple values
            .Select(rs => rs.First()) // select first element from group
            .ToList<PicInfo>() // make the list of picInfo of result