根据属性字符串过滤列表对象

时间:2019-07-12 16:55:52

标签: c# linq

我有一个FTPFileItems对象列表,我需要对这些文件进行排序并根据文件名中的“版本”获取最新版本。

class FtpFileInfo
{
    string FileName;
    DateTime FileDate;
    long FileSize;
    FtpFileType FileType;
}

每个对象中的文件名数据示例

FileName = "XXX_AE_V1_20160812132126.xml"
FileName = "XXX_AE_V2_20160912142126.xml"
FileName = "XXX_AE_V3_20161012152126.xml"

FileName = "XXX_AU_V1_20190213142439.xml"
FileName = "XXX_AU_V2_20190313142439.xml"
FileName = "XXX_AU_V3_20190413142439.xml"
FileName = "XXX_AU_V4_20190513142439.xml"

FileName = "XXX_BR_V1_20170828214049.xml"
FileName = "XXX_BR_V2_20170928214049.xml"
FileName = "XXX_BR_V3_20171028214049.xml"
FileName = "XXX_BR_V4_20171038214049.xml"
FileName = "XXX_BR_V6_20171048214049.xml"

我需要按国家对象将列表压缩到最高文件版本。因此,列表应该以这样的形式结束,但是完整的List对象只是显示文件名部分:

FileName = "XXX_AE_V3_20161012152126.xml"
FileName = "XXX_AU_V4_20190513142439.xml"
FileName = "XXX_BR_V6_20171048214049.xml"

这是我正在尝试的方法,但是我没有得到所需的东西。我由于选择而失去了原始对象,但没有获得最高版本号。

var res = xmlFileNames.Select(s => new
    {
        XXX = s.FileName.Split('_')[0],
        Country = s.FileName.Split('_')[1],
        Version = s.FileName.Split('_')[2],
        FileDate = s.FileName.Split('_')[3]
    })
    .OrderByDescending(x => x.Version)
    .OrderBy(x => x.Country)
    ;

4 个答案:

答案 0 :(得分:2)

您正确的是,第一个select语句正在阻止您维护原始对象。我的建议是将集合按第二个元素分组(您将其称为Country)。然后选择具有最高版本的版本,如下所示。最后按国家订购。

files.GroupBy(x => x.FileName.Split(new char[] { '_' })[1])
      .Select(x => x.OrderByDescending(y => y.FileName.Split(new char[] { '_' })[2]).First())
     .OrderBy(x => x.FileName.Split(new char[] { '_' })[1]);

下面显示了一个完整的解决方案,并根据您的示例提供了一个示例集合。

List<FtpFileInfo> files = new List<FtpFileInfo>() {
    new FtpFileInfo { FileName = "XXX_AE_V1_20160812132126.xml" },
    new FtpFileInfo { FileName = "XXX_AE_V2_20160912142126.xml" },
    new FtpFileInfo { FileName = "XXX_AE_V3_20161012152126.xml" },

    new FtpFileInfo { FileName = "XXX_AU_V1_20190213142439.xml" },
    new FtpFileInfo { FileName = "XXX_AU_V2_20190313142439.xml" },
    new FtpFileInfo { FileName = "XXX_AU_V3_20190413142439.xml" },
    new FtpFileInfo { FileName = "XXX_AU_V4_20190513142439.xml" },

    new FtpFileInfo { FileName = "XXX_BR_V1_20170828214049.xml" },
    new FtpFileInfo { FileName = "XXX_BR_V2_20170928214049.xml" },
    new FtpFileInfo { FileName = "XXX_BR_V3_20171028214049.xml" },
    new FtpFileInfo { FileName = "XXX_BR_V4_20171038214049.xml" },
    new FtpFileInfo { FileName = "XXX_BR_V6_20171048214049.xml" },
};

IOrderedEnumerable<FtpFileInfo> orders = files.GroupBy(x => x.FileName.Split(new char[] { '_' })[1])
                                                .Select(x => x.OrderByDescending(y => y.FileName.Split(new char[] { '_' })[2]).First())
                                                .OrderBy(x => x.FileName.Split(new char[] { '_' })[1]);

foreach (FtpFileInfo order in orders) {
    Console.WriteLine(order.FileName);
}

我收到的输出如下所示,与您提到的是所需的输出相匹配。

  

XXX_AE_V3_20161012152126.xml

     

XXX_AU_V4_20190513142439.xml

     

XXX_BR_V6_20171048214049.xml

答案 1 :(得分:0)

var res = xmlFileNames.Select(s => new
    {
        XXX = s.FileName.Split('_')[0],
        Country = s.FileName.Split('_')[1],
        Version = s.FileName.Split('_')[2],
        FileDate = s.FileName.Split('_')[3]
    })
    .OrderByDescending(x => x.Version, StringComparer.Ordinal)
    .OrderBy(x => x.Country)
    ;

答案 2 :(得分:0)

您可以尝试使用Select范围将其定义为结果,但可以使用该范围避免为每个属性(性能)调用Slipt。使用OrderByThenBy,您将得到所需的排序。最后,使用ToList方法可以使它成为一个通用的更好的结构(匿名对象列表)。

var res = xmlFileNames.Select(s => 
                             {
                                 var a = s.Split('_');
                                 return new 
                                 { 
                                    XXX = a[0], 
                                    Country = a[1], 
                                    Version = a[2], 
                                    FileDate = a[3] 
                                 };
                             })
                             .OrderByDescending(x => x.Version)
                             .ThenBy(x => x.Country)
                             .ToList();

答案 3 :(得分:0)

我遗漏了FtpFileType,因为我不知道有效值是什么,但这应该对您有用。

c#Fiddle

$entries->concat($posts);