【问题标题】:C# return generic list of objects using linqC# 使用 linq 返回对象的通用列表
【发布时间】:2011-11-02 10:05:22
【问题描述】:

我得到了一个如下所示的通用列表:

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() { } 
}

我想做的是:

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

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

如果有人可以帮助我,我将不胜感激。还请解释您的代码。这对我来说是一个学习过程。

提前致谢!

[编辑]

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

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

[/编辑]

【问题讨论】:

  • 你应该更好地描述你的输入+输出。过滤重复文件名列表是什么意思?结果应该是什么形状?

标签: c# linq filter generic-list


【解决方案1】:

这样的事情应该可以工作。我不确定这是否是最好的方法。这不是很有效,因为对于每个元素,您都在再次遍历列表以获取计数。

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

我希望代码不会太复杂而无需解释。我一直认为最好还是自己解决,但如果有任何令人困惑的地方,那就问吧,我会解释的。

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

显然,如果您只想在末尾添加文件名,那么很容易使用 Select 来获取这些文件名的可枚举列表,如果您只希望它们出现一次,则可能使用 Distinct

注意。手写代码,所以请原谅拼写错误。可能无法第一次编译,等等 ;-)

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

用英文我们要做的是:

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

分解它以迭代列表并根据我们使用 Where 方法的标准选择事物。我们 where 方法的条件是

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

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

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

我们感兴趣的文件名在 x 上,我们正在过滤的项目。所以我们要计算有多少项目的文件名与 x.FileName 相同。因此我们的表达式是z=&gt;z.FileName==x.FileName。所以 z 是我们在这个表达式中的变量,而在这个上下文中的 x.FileName 在我们迭代 z 时是不变的。

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

如果您在考虑文件名和哈希值时想要那些重复的部分,那么您可以将 Count 中的部分扩展为 z=&gt;z.FileName==x.FileName &amp;&amp; z.hashValue==x.hashValue

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

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

如果您在考虑文件名和哈希值时想要那些重复的,那么您可以扩展计数中的部分以比较哈希值。由于这是一个数组,您需要使用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();

请注意,我没有创建中间列表,而是直接从原始列表中获取。您可以从中间列表中获取,但如果从原始列表中获取代码与从过滤列表中获取代码将大致相同。

【讨论】:

  • 我需要它作为通用列表,并且我需要获取包含所有重复文件名的列表。我不希望它们在列表中出现一次。
  • 您将从上面的代码中得到一个 IEnumerable,其中所有的 PicInfo 对象都具有重复的文件名。它不会给你一份。我不确定你想要什么通用列表。文件名的通用列表可能是 List 但我不确定你为什么希望它们出现多次。如果你想要一个 PicInfo 列表,那么你只需要调用 ToList() 来获取一个。
  • 是的,我需要 picinfo。所以我会在最后执行 .Tolist() 函数。所以通过这一行,我得到了所有具有相同文件名的对象吗?
  • 是的。如果您仍然无法遵循它,我将通过解释它的工作原理来更新问题。 :)
  • @Yustme:啊,我忘了这是一个数组。这将难以解决平等问题。您可能想使用 SequenceEquals (msdn.microsoft.com/en-us/library/bb348567.aspx) 来比较字节数组。请参阅答案中的更新。
【解决方案2】:

我认为,您必须使用 SequenceEqual 方法来查找重复项 (http://msdn.microsoft.com/ru-ru/library/bb348567.aspx)。 过滤器使用

【讨论】:

    【解决方案3】:
            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
    

    【讨论】:

    • 如果有重复,我希望它们都被退回,而不仅仅是其中一个。这不是'First()'会做的吗?只返回一个重复的?此外,这是一种匿名类型。它需要是一个通用列表。
    • @Yustme: "另外,这是一个匿名类型。它需要是一个泛型列表。" => 然后在 Linq 查询的末尾使用:@987654322 @.
    • 我知道了,谢谢,但是函数“First”怎么样?如果名称和哈希值相等,那是只返回 1 项,还是两者都返回?
    • GroupBy 方法将返回一组组,每个组由具有相同文件名的那些东西组成。 rs.First 将因此获得给定组的第一个 PicInfo。这意味着您最终只会得到每个文件名一个 PicInfo,我认为这不是您想要的。我怀疑有一种方法可以将它们全部重新排列成一个序列,但我想不出它是什么。
    • 我正在尝试 All(),但该函数不接受 0 个参数。我不确定将它作为参数传递什么。这正是我需要的。文件名和哈希值都已检查。
    猜你喜欢
    • 1970-01-01
    • 2012-07-19
    • 1970-01-01
    • 2015-01-05
    • 2023-03-24
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多