Copied to clipboard

Flag this post as spam?

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


  • Levente Kosa 136 posts 352 karma points
    Apr 30, 2020 @ 15:19
    Levente Kosa
    0

    List of numbers between a range

    Hi,

    I would like to create a list between a range of numbers with Razor, like the minimum number is 100,000 and the maximum is 1,200,000, so the list would be 100,000; 200,000; 300,000; ...1,200,000 100,000 would be the steps. Unfortunately I have to put everything into a data attribute as a pricesList, so, so far I have this:

    var developments = Model.Root().Children.Where(x => x.IsDocumentType("developments")).FirstOrDefault();
    var prices = new List<int>();
    var pricesList = "";
    var priceValue = "";
    var storedFloor = 0;
    var storedCeiling = 0;
    
    foreach (var development in developments.Children.Where(x => x.IsVisible())) {
        var plots = development.Children.Where(x => x.IsVisible());
    
        prices.AddRange(plots.Select(x => x.Value<int>("price")));
        foreach (var price in prices.Distinct().OrderBy(x => x))
        {
            var floor = 0;
            var ceiling = 0;
            var storedPrice = price;
    
            if(floor == ceiling){
                storedPrice = price + 1;    
            }
    
            floor = (int)(Math.Floor((int)price / 100000.0) * 100000);
            ceiling = (int)(Math.Ceiling((int)storedPrice / 100000.0d) * 100000);
    
            if(storedFloor != floor && storedCeiling != ceiling){
                storedFloor = floor;
                storedCeiling = ceiling;
    
                priceValue = "£" + floor.ToString("#,##0") + " - " + "£" + ceiling.ToString("#,##0");
    
                pricesList += "<option value='" + floor + "-" + ceiling + "'>" + @priceValue + "</option>";
            }
        }
    }
    

    This only gives me the min and max value by children, not together. enter image description here

  • Kevin Jump 2342 posts 14869 karma points MVP 8x c-trib
    Apr 30, 2020 @ 17:55
    Kevin Jump
    0

    Oh I like a little coding challenge 😊

    I would swap the foreach out with a old school for loop, just because you can then go back in the loop to get the previous price.

    So I assuming you are getting the prices from content nodes - into a list of ints called prices. if that list is ordered and a list.

    UPDATE: OK so i missed that the prices where not the rounded numbers. the following will round those values into the nearest 100,000.

    prices = prices.Select(x => (int)(Math.Celing(x / 100000d) * 100000))
        .Distinct().OrderBy(x => x).ToList();
    

    then i would use a for loop to start from the second item (1 in the index),

    <select>
        @for (int p = 1; p < prices.Count; p++)
        {
            var priceString = string.Format("£{0:#,##0} - £{1:#,##0}", prices[p - 1], prices[p]);
            var priceValue = string.Format("{0}-{1}", prices[p - 1], prices[p]);
    
            <option value="@priceValue">@priceString</option>
        }
    </select>
    

    that gives you the list with ranges, .

  • Kevin Jump 2342 posts 14869 karma points MVP 8x c-trib
    Apr 30, 2020 @ 18:16
    Kevin Jump
    0

    OK,

    I wasn't happy with that version :(

    It returns whole lists e.g.

    • £100,000 - £200,000
    • £200,000 - £400,000
    • £400,000 - £500,000

    and i am not sure you wanted that (for example do you want the middle on to be £300,000 - £400,000) ?

    So

    Once you have all the prices grouped. If we assume that you just want the 100,000 ranges.

    <select>
        @for(int p = 0; p < prices.Count; p++)
        {
            var priceValue = string.Format("{0}-{1}", prices[p] - 1000000, prices[p]);
            var priceString = string.Format("£{0:#,##0} - £{1:#,##0}", prices[p] - 100000, prices[p]);
    
            <option value="@priceValue">@priceString</option>
        }
    </select>
    

    this would return

    • £100,000 - £200,000
    • £300,000 - £400,000
    • £400,000 - £500,000

    (if for example there are no 200,000 plot values)

    So for compleatness (and with a step variable so you can change it).

    @inherits UmbracoViewPage<IPublishedContent>
    @{
        var priceStep = 100000;
        var prices = new List<int>();
    
        // get all the prices from all the developments 
        var developments = Model.Root().Children.Where(x => x.IsDocumentType("developments")).FirstOrDefault();
        foreach (var development in developments.Children.Where(x => x.IsVisible()))
        {
            var plots = development.Children.Where(x => x.IsVisible());
            prices.AddRange(plots.Select(x => x.Value<int>("price")));
        }
    
    
        // round them up, and then pick only distinct the rounded up values. 
        prices = prices.Select(x => (int)(Math.Ceiling(x / (decimal)priceStep) * priceStep))
            .Distinct().OrderBy(x => x).ToList();
    
        // loop through the rounded values and produce the list 
        <select>
            @for (int p = 0; p < prices.Count; p++)
            {
                var priceValue = string.Format("{0}-{1}", prices[p] - priceStep, prices[p]);
                var priceString = string.Format("£{0:#,##0} - £{1:#,##0}", prices[p] - priceStep, prices[p]);
    
                <option value="@priceValue">@priceString</option>
            }
        </select>
    }
    
  • Levente Kosa 136 posts 352 karma points
    Apr 30, 2020 @ 18:35
    Levente Kosa
    0

    HI Kevin,

    Thank you for your help. I tried the code, now I have this version. Only difference that everything goes into a data attribute, like this:

    var developments = Model.Root().Children.Where(x => x.IsDocumentType("developments")).FirstOrDefault();
    var formEmailAddress = "";
    var prices = new List<int>();
    var priceStep = 100000;
    var pricesList = "";
    var priceValue = "";
    var storedFloor = 0;
    var storedCeiling = 0;
    
    foreach (var development in developments.Children.Where(x => x.IsVisible()) {
        var plots = development.Children.Where(x => x.IsVisible());
    
        prices.AddRange(plots.Select(x => x.Value<int>("price")));
        prices = prices.Select(x => (int)(Math.Ceiling(x / (decimal)priceStep) * priceStep)).Distinct().OrderBy(x => x).ToList();
    
        for (int p = 0; p < prices.Count; p++) {
            priceValue = string.Format("{0}-{1}", prices[p] - priceStep, prices[p]);
            var priceString = string.Format("£{0:#,##0} - £{1:#,##0}", prices[p] - priceStep, prices[p]);
    
            pricesList += "<option value='" + priceValue + "'>" + @priceString + "</option>";
        }
    }
    
    <div data-budget="@Html.Raw(pricesList)">...</div>
    

    Unfortunately, don't know how, but the result is the same:

    data-budget="<option value='200000-300000'>£200,000 - £300,000</option><option value='300000-400000'>£300,000 - £400,000</option><option value='1100000-1200000'>£1,100,000 - £1,200,000</option><option value='100000-200000'>£100,000 - £200,000</option><option value='200000-300000'>£200,000 - £300,000</option><option value='300000-400000'>£300,000 - £400,000</option><option value='1100000-1200000'>£1,100,000 - £1,200,000</option>"
    

    Maybe just need to order by value and exclude the duplicates. Is that possible?

  • Kevin Jump 2342 posts 14869 karma points MVP 8x c-trib
    Apr 30, 2020 @ 18:40
    Kevin Jump
    0

    yeah i would split the loops out.

    so do this to get all the prices across all the plots.

    foreach (var development in developments.Children.Where(x => x.IsVisible()) 
    {
        var plots = development.Children.Where(x => x.IsVisible());
        prices.AddRange(plots.Select(x => x.Value<int>("price")));
    }
    

    then distinct and round etc. after the loop

    prices = prices.Select(x => (int)(Math.Ceiling(x / (decimal)priceStep) * priceStep)).Distinct().OrderBy(x => x).ToList();
    

    then the for loop - that way you get the distinct list across all developments,

    at the moment it looks like you are doing the for loop inside the other loop, not sure why is there a reason ?

  • Levente Kosa 136 posts 352 karma points
    Apr 30, 2020 @ 18:50
    Levente Kosa
    0

    Yeah, my bad. Now for loop is outside of the foreach. Much-much better, however, some values are missing 400,000-500,000 ; 500,000-600,000 ; 600,000-700,000 etc

    enter image description here

    foreach (var development in developments.Children.Where(x => x.IsVisible()) {
        var plots = development.Children.Where(x => x.IsVisible());
    
    
        prices.AddRange(plots.Select(x => x.Value<int>("price")));
        prices = prices.Select(x => (int)(Math.Ceiling(x / (decimal)priceStep) * priceStep)).Distinct().OrderBy(x => x).ToList();
    }
    
    for (int p = 0; p < prices.Count; p++) {
        priceValue = string.Format("{0}-{1}", prices[p] - priceStep, prices[p]);
        var priceString = string.Format("£{0:#,##0} - £{1:#,##0}", prices[p] - priceStep, prices[p]);
    
        pricesList += "<option value='" + priceValue + "'>" + @priceString + "</option>";
    }
    
  • Kevin Jump 2342 posts 14869 karma points MVP 8x c-trib
    Apr 30, 2020 @ 18:58
    Kevin Jump
    100

    They will be missing because there are no prices in those ranges ?

    So there are two options,

    you can either have all ranges, irrespective of them actually having values in ? e.g

    • 100,000 - 200,000
    • 200,000 - 300,000
    • 300,000 - 400,000, etc

    if so - you could probibly bypass the whole collection thing and put a for loop in to build them.

    for(int p = priceStep; p < 1200000; p += priceStep)
    {
        // forloop will increment in 100,000's 
        // this doesn't need the prices array 
        var priceString = string.Format("£{0:#,##0} - £{1:#,##0}", p, p + priceStep);
    
        // ....
    }
    

    or

    If you still want to use the data but want the ranges to meet each other ,

    e.g

    • £100,000 - £200,000
    • £200,000 - £300,000
    • £300,000 - £1,100,000
    • £1,100,000 - £1,200,000

    then the first example did that, by doing the for loop from the second value (1 in the index) and then putting the p-1 value in the loop:

        @for (int p = 1; p < prices.Count; p++)
        {
            var priceString = string.Format("£{0:#,##0} - £{1:#,##0}", prices[p - 1], prices[p]);
            var priceValue = string.Format("{0}-{1}", prices[p - 1], prices[p]);
    
            <option value="@priceValue">@priceString</option>
        }
    
  • Levente Kosa 136 posts 352 karma points
    Apr 30, 2020 @ 19:08
    Levente Kosa
    0

    Thank you Kevin for you help, you really nailed it. Cheers!!

Please Sign in or register to post replies

Write your reply to:

Draft