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 1932 posts 6722 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 1932 posts 6722 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 1932 posts 6722 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 1932 posts 6722 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 1932 posts 6722 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 1932 posts 6722 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 1932 posts 6722 karma points MVP 2x c-trib
    Mar 24, 2023 @ 08:41
    Huw Reddick
    100

    Happy to help.

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies