Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Morten Peter Hagh Jensen 25 posts 85 karma points
    Mar 22, 2023 @ 15:18
    Morten Peter Hagh Jensen
    0

    Sorting string with number in Umbraco razor

    In a Umbraco 8 site I have an address in a string, so that string will contain a number, like: Street Road 2, Street Road 14, Street Road 22b etc.

    I am sorting the list by address (among other values)

    var apartments = Umbraco.Content(Guid.Parse("f3c9c894-16e5-491e-b39f-77bf2cb13c6f"))
    .ChildrenOfType("ApartmentItem")
    .Where(x => x.IsVisible()).OrderBy(x => x.Value("apartmentItemStatus")
    .ToString().Replace(" ", "")).ThenBy(x => x.Name.ToString().Replace(" ", ""));
    

    The expected result should be

    Street Road 2
    Street Road 14
    Street Road 22b
    

    But the actual result is

    Street Road 14
    Street Road 2
    Street Road 22b
    

    I know it is because of alphanumeric, but I can't figure out how to sort it correctly. Has anyone had a similar issue?

  • Huw Reddick 1929 posts 6697 karma points MVP 2x c-trib
    Mar 22, 2023 @ 15:25
    Huw Reddick
    0

    it is not really possible to sort that way using strings, it will alsways put 1 before 2, if it was 02 then it would sort it, you could try splitting the string into a keyvalue pair and convert the numbers to actual numbers, but that would also break because of 22b :)

  • Huw Reddick 1929 posts 6697 karma points MVP 2x c-trib
    Mar 22, 2023 @ 15:26
    Huw Reddick
    0

    This is nothing to do with Umbraco, it is just the way string sorting works

  • Huw Reddick 1929 posts 6697 karma points MVP 2x c-trib
    Mar 22, 2023 @ 15:41
    Huw Reddick
    0

    You would need to implement a custom IComparer

    public class CustomComparer : IComparer<string>
    {
        public int Compare(string x, string y)
        {
            var regex = new Regex("(\\d+)");
    
            // run the regex on both strings
            var xRegexResult = regex.Match(x);
            var yRegexResult = regex.Match(y);
    
            // check if they are both numbers
            if (xRegexResult.Success && yRegexResult.Success)
            {
                return int.Parse(xRegexResult.Groups[1].Value).CompareTo(int.Parse(yRegexResult.Groups[1].Value));
            }
    
            // otherwise return as string comparison
            return x.CompareTo(y);
        }
    }
    

    You would then use it like

    var myComparer = new CustomComparer();
    myListOfStrings.Sort(myComparer);
    
  • Huw Reddick 1929 posts 6697 karma points MVP 2x c-trib
    Mar 22, 2023 @ 16:15
    Huw Reddick
    0

    just test it and you acually need to do 2 sorts otherwise things like 22d and 22a will not sort correctly, so you need to use the comparer like below

    var myComparer = new CustomComparer();
    myStrings.Sort();
    myStrings.Sort(myComparer);
    
  • Morten Peter Hagh Jensen 25 posts 85 karma points
    Mar 23, 2023 @ 16:06
    Morten Peter Hagh Jensen
    0

    Thanks! I really appreciate your help!

    Forgive my stupidity! Can you give an example of how to implement this in my use case:

     var apartments = Umbraco.Content(Guid.Parse("f3c9c894-16e5-491e-b39f-77bf2cb13c6f")).ChildrenOfType("ApartmentItem").Where(x => x.IsVisible()).OrderBy(x => x.Value("apartmentItemStatus").ToString().Replace(" ", "")).ThenBy(x => x.Name.ToString().Replace(" ", "")).ToList();
    

    Should I place the class in App_Code? I have done that now and if I use your example I get:

    cannot convert from 'holmemollevej.App_Code.CustomComparer' to 'System.Collections.Generic.IComparer<Umbraco.Core.Models.PublishedContent.IPublishedContent>'
    
  • Huw Reddick 1929 posts 6697 karma points MVP 2x c-trib
    Mar 23, 2023 @ 16:18
    Huw Reddick
    0

    I'm guessing that is because apartments is a List of IPublishedContent.

    I'll have a play and see if I can come up with something for you

  • Morten Peter Hagh Jensen 25 posts 85 karma points
    Mar 23, 2023 @ 16:30
    Morten Peter Hagh Jensen
    0

    Heroes isn't always wearing capes!

  • Huw Reddick 1929 posts 6697 karma points MVP 2x c-trib
    Mar 23, 2023 @ 16:34
    Huw Reddick
    0

    No guarentees, but try this

    Create a new CustomNameComparer.cs file, you should be able to create it anywhere in your project.

    public class CustomNameComparer : IComparer<IPublishedContent>
    {
        public int Compare(IPublishedContent x, IPublishedContent y)
        {
            var regex = new Regex("(\\d+)");
    
            // run the regex on both strings
            var xRegexResult = regex.Match(x.Name);
            var yRegexResult = regex.Match(y.Name);
    
            // check if they are both numbers
            if (xRegexResult.Success && yRegexResult.Success)
            {
                return int.Parse(xRegexResult.Groups[1].Value).CompareTo(int.Parse(yRegexResult.Groups[1].Value));
            }
    
            // otherwise return as string comparison
            return x.Name.CompareTo(y.Name);
        }
    }
    

    where you are doing

    var apartments = Umbraco.Content(Guid.Parse("f3c9c894-16e5-491e-b39f-77bf2cb13c6f")).ChildrenOfType("ApartmentItem").Where(x => x.IsVisible()).OrderBy(x => x.Value("apartmentItemStatus").ToString().Replace(" ", "")).ThenBy(x => x.Name.ToString().Replace(" ", "")).ToList();
    

    Change it to

    var apartments = Umbraco.Content(Guid.Parse("f3c9c894-16e5-491e-b39f-77bf2cb13c6f")).ChildrenOfType("ApartmentItem").Where(x => x.IsVisible()).OrderBy(x => x.Value("apartmentItemStatus").ToString().Replace(" ", "")).ToList();
    var myComparer = new CustomNameComparer ();
    apartments.Sort(myComparer);
    
  • Morten Peter Hagh Jensen 25 posts 85 karma points
    Mar 23, 2023 @ 20:51
    Morten Peter Hagh Jensen
    0

    I had to move the order by apartmentItemStatus to a new var with the list after sorting, but other than that it works perfectly!

    Thanks for the help! Really appreciate it!

  • Huw Reddick 1929 posts 6697 karma points MVP 2x c-trib
    Mar 24, 2023 @ 08:41
    Huw Reddick
    100

    Happy to help.

Please Sign in or register to post replies

Write your reply to:

Draft