在这种特殊情况下如何处理排序? [英] How do I deal with sorting in this special case?

查看:102
本文介绍了在这种特殊情况下如何处理排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Vb.net使用VS 2015进行编码。



我为我们的工程人员创建了一个应用程序,可以在输入打印编号时检索最新版本的打印(pdf格式)。文件以这种格式命名 - 图纸number_revision_page_date

示例0092933_C_1-2_061217.pdf



我有两个需要帮助的问题。我使用带有orderbydescending lambda函数的directory.getfiles找到这些文件。我曾经使用完整的文件名,但是,我们的图纸进入双字母转速。转速是a到z - 然后用aa,ab,ac等重复。 Windows按文件名排序时会在z之前列出rev aa。因此,当按文件名降序排序时,它总是选择z作为最高转速。因为它在列中从左到右排序字符。所以,我的下一次尝试是使用日期解析,使用日期解析精确地将最后6位数字转换为日期。我现在的问题是,出于某种原因,rev b和c是在同一天完成的。 b恰好首先显示在结果中......但由于日期是相同的,因此它只查看日期或者可能是结果。



我最初查看系统上次修改日期 - 文件属性但是如果某人因任何原因重新创建旧PDF,该日期现在比最新日期更新rev并被选中,因此无法使用。



我有什么选择来确保我选择最新的文件?



这是我的获取文件声明的一个例子。



我尝试过:



Vb.net using VS 2015 to code.

I've created an app for our engineering staff, that retrieves the "latest" version of print (pdf format) - when print number is entered. Files are named in this format - drawing number_revision_page_date
example 0092933_C_1-2_061217.pdf

I have two issues that I need help with. I find the files using directory.getfiles with an orderbydescending lambda function. I used to use the full filename however, we have drawings that get into double letter revs. revs are a to z - then repeat with aa, ab, ac...etc. Windows, when sorting by filename will list rev aa before z. so it always picks z as the top rev when sorted descending by filename. because it sorts characters left to right in columns. so, my next try was using the date in the filename by using a date parse exact converting the last 6 digits to a date. My problem now, is that for some reason rev b and c were done on the same day. b happens to show up in the results first ... but since it's only looking at the date either or can be the result since the dates are the same.

I originally looked at the system last modified date - file property however in an event where someone recreates an old PDF for whatever reason, that date is now newer than the latest rev and gets picked, so that cannot be used.

what are my options here to assure I'm picking the latest file?

here's an example of my get files statement.

What I have tried:

Dim result = Directory.GetFiles(fp, f).OrderByDescending(Function(x) Date.ParseExact(x.Substring(x.Length - 10, 6), "MMddyy", enusCulture)).First

推荐答案

要求:双字母转 - a到z - 然后用aa重复,一个b,ac ......等。与z之前的rev aa。 alpha之前的长度,然后是alpha的降序。



因此,对于修订版本的自定义排序,IComparer<t>界面

[ ^ ]最适合此任务。这是一个比较器,它将根据长度进行排序,然后是alpha修订字母:

Requirement: Double letter revs - a to z - then repeat with aa, ab, ac...etc. with rev aa before z. Length before alpha, then descending by alpha.

So, for custom sorting of the revision version, the IComparer<t> Interface
[^] is best suited for this task. Here is a comparer that will sort based on length, then alpha revision letter:
Class RevisionComparer
    Implements IComparer(Of String)

    Private Function IComparer_Compare(x As String, y As String) As Integer _
        Implements IComparer(Of String).Compare

        ' same values
        If x = y Then Return 0

        ' different lengths
        If x.Length > y.Length Then Return 1
        If x.Length < y.Length Then Return -1

        ' the same length, more work required
        If x.Length = y.Length Then

            For i As Integer = 0 To x.Length - 1

                ' check by position
                If x(i) > y(i) Then Return 1
                If x(i) < y(i) Then Return -1

            Next

        End If

        ' must be identical, so no change
        Return 0

    End Function

End Class



在我们可以做任何事情之前,我们需要创建并测试 RevisionComparer 类:


Before we can do anything, we need to create and test the RevisionComparer class:

Module Module1

    Sub Main()

        Dim testRevisions = New List(Of String)() From {
            "c",
            "aa",
            "az",
            "ba",
            "bz",
            "aaa",
            "bca",
            "cba",
            "aza",
            "azz"
        }

        Dim sortedRevisions = testRevisions.OrderByDescending(Function(x) x, New RevisionComparer())

        For Each item In sortedRevisions
            Console.WriteLine(item)
        Next

        Console.WriteLine("-- DONE --")
        Console.ReadKey()

    End Sub

End Module



哪个输出:


Which outputs:

cba
bca
azz
aza
aaa
bz
ba
az
aa
c
-- DONE --



好​​的,现在我们已准备好迎接主要的ev ent。



要求是:

1.文件以这种格式命名 - 图号number_revision_page_date

.. ..示例0092933_C_1-2_061217.pdf

2.双字母转 - a到z - 然后用aa,ab,ac等重复。

3. date是在修改之前??? (假设未澄清)



这是基于上述3个确定要求的解决方案。 (注意:易于更改)



首先,我们需要将文件名分成几部分:


Okay, now we are ready for the main event.

Requirements are:
1. Files are named in this format - drawing number_revision_page_date
.... example 0092933_C_1-2_061217.pdf
2. double letter revs - a to z - then repeat with aa, ab, ac...etc.
3. date is before revision??? (assumed as not clarified)

Here is a solution based on the above 3 identified requirements. (note: Easy to change)

First, we need to break the filename out into its parts:

Class FileType
    Public Property ID As String
    Public Property Name As String
    Public Property Revision As String
    Public Property [Date] As String
    Public Property Pages As String
End Class



使用 RevisionComparer 上面我们现在可以对文件名进行排序:


Using the RevisionComparer above we can now sort the filenames:

Module Module1

    Sub Main()

        ' test data
        Dim files = New List(Of String)() From {
            "0092933_C_1-2_061117.pdf",
            "0092933_Z_1-2_120617.pdf",
            "0092933_AZ_1-2_120617.pdf",
            "1092933_AB_1-2_061117.pdf",
            "1092933_Z_1-2_120617.pdf",
            "1092933_CZ_1-2_120617.pdf"
        }

        Dim data As New List(Of FileType)()

        For Each file In files

            ' break up the filename
            Dim parts = IO.Path.GetFileNameWithoutExtension(file).Split(New Char() {"_"c}, StringSplitOptions.RemoveEmptyEntries)

            ' valid number of parts
            If parts.Length = 4 Then

                Dim fileDate = Nothing
                DateTime.TryParse(parts(2), fileDate)

                data.Add(New FileType() With {
                    .ID = parts(0),
                    .Revision = parts(1),
                    .[Date] = parts(2),
                    .Pages = parts(3),
                    .Name = file
                })

            End If
        Next

        ' sort the files by: date desc, then revision desc...
        Dim sorted = data.OrderByDescending(Function(x) x.[Date]) _
                        .ThenByDescending(Function(x) x.Revision, New RevisionComparer()) _
                        .GroupBy(Function(x) x.ID) _
                        .Select(Function(x) x.First())

        ' report the results
        For Each item In sorted
            Console.WriteLine(item.Name)
        Next

        Console.WriteLine("-- DONE --")
        Console.ReadKey()

    End Sub

End Module



哪个输出:


Which outputs:

1092933_CZ_1-2_120617.pdf
0092933_AZ_1-2_120617.pdf
-- DONE --





更新:您要求仅限Linq解决方案,答案是肯定的,你可以避免额外的类,并使它成为一个非常长的Linq查询,但它归结为可读性和ma intainability。上面的解决方案勾选了这两个框。



但是,你要求一个单行Linq查询,所以在这里,由于自定义排序使用上面的Comparer需求。使用的所有部件都在以上更有说服力的解决方案中:



UPDATE: You ask for a "Linq only solution" and the answer is yes, you can avoid extra classes and make it one very long Linq query but then it comes down to readability and maintainability. The above solution ticks both of these boxes.

However, you asked for a one liner Linq query, so here it is, using the above Comparer due to the custom sorting requirement. All parts used are in the above more eloquent solution:

Dim sortedV2 = files.Select(Function(x) IO.Path.GetFileNameWithoutExtension(x).Split(New Char() {"_"c}, StringSplitOptions.RemoveEmptyEntries)) _
                    .OrderByDescending(Function(x) x(2)) _
                    .ThenByDescending(Function(x) x(1), New RevisionComparer()) _
                    .GroupBy(Function(x) x(0)) _
                    .Select(Function(x) x.First()) _
                    .Select(Function(x) String.Join("_", x) + ".pdf")

' report the results
For Each item In sortedV2
    Console.WriteLine(item)
Next



注意:这个Linq单线解决方案的问题在于,如果你有错误的话命名文件Linq语句将抛出异常,但上面的原始解决方案不会。


Note: the problem with this Linq one-liner solution is that if you have an incorrectly named file the Linq statement will throw an exception, however the above "original" solution won't.


这篇关于在这种特殊情况下如何处理排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆