Problem with LINQ

Asked

Viewed 95 times

1

I am converting PDF to TIFF and converting page by page to a temporary folder and at the end I will fetch those files to join them as in the original file. My code is as follows: (I used what is in my reply question):

string pastapdf = AppDomain.CurrentDomain.BaseDirectory + "temporario\\" + Path.GetFileNameWithoutExtension(e[i]);
Directory.CreateDirectory(pastapdf);
string pdfFile = Path.Combine(pastapdf, e[i]);
for (int h = 0; h <= (pdfReader.NumberOfPages - 1); h++)
{
    using (var document = PdfiumViewer.PdfDocument.Load(pdfFile))
    {
         var image = document.Render(h, dpi, dpi, true);
         image.Save(pastapdf + "\\" + Path.GetFileNameWithoutExtension(e[i]) + "_" + h.ToString() + ".tif", ImageFormat.Tiff);
         image.Dispose();
    }
}
string save = output + "\\" + Path.GetFileNameWithoutExtension(e[i]) + ".tif";
string[] tifffiles = GetFiles(pastapdf, "*.tif");
var finalfiles = tifffiles.OrderBy(f => 
    new string(f.Where(char.IsLetter).ToArray())).ThenBy(f => { 
    int number; if (int.TryParse(new string(f.Where(char.IsDigit).ToArray()), out number)) 
    return number; return -1; } ).ToList(); //código LINQ para ordenar

JoinTiffLZW(finalfiles.ToArray(), save);
Invoke(new Action(() => { pbar.PerformStep(); pdfReader.Dispose(); }));

You should do: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11.... And it’s doing: 1, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9....

My question is if anyone can tell me another way to sort the list or what’s wrong with my code?

TEST

I uploaded a 40-page PDF. I divided and converted them all, then I fetched the files: parte 1 do exemplo

And then I should order with LINQ, but the result is this: parte 2 do exemplo

And it should be in the right order, so when I get everybody together, it’s the wrong order.

  • First thing: The VS update itself might not have caused this, only if you installed some framework and/or something related together, but that shouldn’t change. Until pq you would need to change the target framework you are using in your project, so it doesn’t seem to make sense. Other than that, it is impossible to happen what you comment on the question because the ordering is numerical, or you are testing with the wrong code block, or missing information in the question.

  • 1

    My tip for you is: Isolate the code and test with a pre-defined data set. Also, always leave a test case ready in your question - especially one that is failing, because then whoever wants to help you has a starting point.

  • @LINQ I thought it might be the update because before it was working. I will add more code to the question and I will test as you said.

  • 1

    Yes, quiet. This is a very normal mess, especially since the problem started to appear after updating. But do it, add more details that is better to try to help you.

  • @LINQ already added a test and changed the question.

  • 1

    I’ll write you a reply. Look, I realized that you already have a certain site time. After answering I will edit your question and format it and you use this question as formatting basis for your next questions, it may be?

  • @LINQ right, but what’s wrong with my question?

  • is ordering strings instead of numbers... values to sort are always between characters _ and . ?

  • @All right, you stay " name _0"

Show 5 more comments

2 answers

4


Probably this code has never worked before, at least not in the test case that was quoted in your question.

What happens in your code is this.

  1. GetFiles returns a list of strings (in fact, it would be good to have mentioned this in the question).

    From the image, I saw that the list of strings would be something like

    var tifffiles = new[] 
    { 
        "C:\\Qualquercoisa_v2\\anual_2009\\anual_2009_0", 
        "C:\\Qualquercoisa_v2\\anual_2009\\anual_2009_2", 
        "C:\\Qualquercoisa_v2\\anual_2009\\anual_2009_1", 
        "C:\\Qualquercoisa_v2\\anual_2009\\anual_2009_5", 
        "C:\\Qualquercoisa_v2\\anual_2009\\anual_2009_11", 
        "C:\\Qualquercoisa_v2\\anual_2009\\anual_2009_4", 
        "C:\\Qualquercoisa_v2\\anual_2009\\anual_2009_10",  
    };
    
  2. In this string list is called the method OrderBy with the following sorting function

    new string(f.Where(char.IsLetter).ToArray()
    

    This means that for each element of the collection (that of step 1) a new one will be created string containing only the letters - because only letters return true in the call for char.IsDigit.

    That is, the elements used in sorting will be - note that this does not alter the original elements:

    CQualquercoisavanualanual
    CQualquercoisavanualanual
    CQualquercoisavanualanual
    CQualquercoisavanualanual
    CQualquercoisavanualanual
    CQualquercoisavanualanual
    CQualquercoisavanualanual
    

    Therefore, the ordered collection that is returned keeps all elements in the same position that they were.

  3. A call is made to the method ThenBy, using the following sorting function:

    int number; 
    if (int.TryParse(new string(f.Where(char.IsDigit).ToArray()), out number)) 
        return number; 
    return -1;
    

    What this function does - for each item in the collection - is the following:

    1. f.Where(char.IsDigit) selects all numbers from the original string;
    2. new string creates a new string with the selected numbers;
    3. int.TryParse tries to convert the generated string into a 32-bit integer (point of attention) and returns true if the conversion works and false otherwise; and
    4. return returns the converted value if the conversion worked or -1 otherwise.

    Now let’s try to apply this to the first element of array original

    C:\\Qualquercoisa_v2\\anual_2009\\anual_2009_0
    
    1. Select all numbers: 2200920090
    2. Create a string with these numbers: "2200920090"
    3. Try to convert to int: Problem here


    See the test code in repl.it

    Now just understand what is causing this error =)

    What happens there is that the numbers are larger than an integer of 32 bits. For this specific case (and several more) you can simply switch to a 64-bit integer (long). That is, change the second sort function to

    long number; 
    if (long.TryParse(new string(f.Where(char.IsDigit).ToArray()), out number)) 
    ... 
    

My advice is actually to review this code and try to rewrite it.

  • 1

    LINQ solving native problems of its own, impressive nature.

  • 1

    In addition to an excellent explanation of the problem and the code, a good answer.

  • The best part is the last sentence :)

1

The idea here will be to create an object of anonymous type to assist sorting, with the filename and value to sort... this example takes into account that the value to sort is always between the last character _ and the .

    string[] files = new string[] {

        @"C:\Users\Utilizador\Pictures\revenche_2019_0.png",
        @"C:\Users\Utilizador\Pictures\revenche_2019_1.png",
        @"C:\Users\Utilizador\Pictures\revenche_2019_11.png",
        @"C:\Users\Utilizador\Pictures\revenche_2019_2.png",
        @"C:\Users\Utilizador\Pictures\revenche_2019_12.png",
        @"C:\Users\Utilizador\Pictures\revenche_2019_3.png"
    };

    var result = files.Select(f => new
    {
        file = f,
        index = int.Parse(string.Concat(f.Skip(f.LastIndexOf('_') + 1).TakeWhile(f2 => f2 != '.')))
    }).OrderBy(an => an.index)
    .Select(an => an.file)
    .ToList();

    result.ForEach(f => Console.WriteLine(f));
  • But then getting mixed up with two different years is over, right.

  • His answer worked like that of LINQ, the question is that yours is limited to names with this format and LINQ can be used in several cases. Although your answer is right, LINQ’s works better for me.

  • @LINQ, therefore, in the name of the folder already has the year, I do not know if it can have other files... but its solution also has this problem of the year, imagine that the file 0 of 2009 brings the value 2200920090, and the 10 of 2008 will bring 22009200810, this last one is bigger than the first one....

  • 1

    @Sofiarodrigues the important thing is to solve your problem :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.