Copied to clipboard

Flag this post as spam?

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


  • Dan 1285 posts 3917 karma points c-trib
    Aug 16, 2012 @ 14:14
    Dan
    0

    Get x random numbers within a range

    Hi,

    I'm trying to pick 5 nodes at random.  I've tried a couple of ways of doing this (e.g the two mentioned here: http://our.umbraco.org/forum/developers/xslt/6605-Best-Way-To-Get-Random-Nodes-From-Specific-Node) but because the original data set is so large these are either unreliable or very poorly performing.  So before I create my own XSLT extension I thought I'd try the magical uComponents.

    I notice there are some extension methods for generating random numbers in uComponents, but I'm ideally looking for something that will return 5 random numbers within a range.  There's a method called 'GetRandomNumbers' but it only takes a single integer as an input parameter and I think it only outputs a range between 1 and 10.

    There's also a GetRandomNumber method which takes a maximum and optional minimum parameter, so this might be a reasonable solution - just to call this method 5 times.

    Has anyone come across any other ways of doing this, or is there anything else in uComponents that could achieve the same thing?

    Thanks!

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Aug 16, 2012 @ 14:23
    Lee Kelleher
    0

    Hi Dan,

    Yeah, just checked, the GetRandomNumbers function takes the input value as the max number, and the start number defaults to 1 ... I can add an overload to make it accept a start and end value, and pick random numbers within the range?

    Would that work for you?

    Cheers, Lee.

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Aug 16, 2012 @ 14:29
    Lee Kelleher
    1

    There is one called "RandomSort(XPathNavigator node, int count)"in the XML extensions.  You can pass it a nodeset (from XSLT) and a count, then it will sort the nodes in random order and return the nodeset limited by the count.

    (This isn't on the documentation page ... I do need to give the doco some TLC) :-)

    Cheers, Lee

  • Dan 1285 posts 3917 karma points c-trib
    Aug 16, 2012 @ 14:44
    Dan
    0

    Thanks Lee.  Ordinarily that would do just the job, but I think the issue with this particular situation is that the data-set is large (3000+ nodes, 150 properties per node) so I fear that using the RandomSort method or the RandomNode method in the 'xml' extension may be pretty slow?  You can probably advise whether it'd be any quicker, but the route I was going to take was to generate a nodeset of just node ids from the original data-set, count these, generate 5 random numbers via an XSLT extension within the range 1 to total-count, then basically grab the node ids from the 5 random positions and run a 'GetXmlNodeById' on those.  This way the only time the full 150-property nodes are being processed is at the very end, just for the 5 selected nodes.  I thought this may be better performing than putting everything into a node-set and trying to process that?  Certainly having tried to do a dynamic sort on the full nodeset through just XSLT is really slow - maybe the extension handles it differently?

    Does this make any sense at all? ;)

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Aug 16, 2012 @ 15:21
    Lee Kelleher
    1

    It does make sense, and you're right, the RandomSort/RandomNode would most likely be slower performance.

    If you can build up a CSV of nodeIds, then I'd be tempted to try the following XSLT extension:

    namespace Our.Umbraco
    {
        using System;
        using System.Linq;
    
        [umbraco.XsltExtension("our.umbraco")]
        public class XsltExtensions
        {
            public static string GetRandomItemsFromCsv(string csv, int count)
            {
                // if empty, return empty
                if (string.IsNullOrWhiteSpace(csv))
                    return string.Empty;
    
                // split CSV, load into array
                var list = csv.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
    
                // randomly sort the order of the list (based on GUIDs)
                var items = list.OrderBy(s => Guid.NewGuid()).ToList();
    
                // if the number of items is larger than the count...
                if (items.Count >= count)
                {
                    // ... then take the first [x] items
                    items = items.Take(count).ToList();
                }
    
                // rebuild the CSV
                return string.Join(",", items.ToArray());
            }
        }
    }
    <xsl:value-of select="our.umbraco:GetRandomItemsFromCsv('1111,2222,3333,4444', 2)" />

    I haven't tested this, so might need some tinkering... let me know how it works out - will probably add it to next uComponents release! ;-)

    Cheers, Lee.

  • Dan 1285 posts 3917 karma points c-trib
    Aug 16, 2012 @ 15:25
    Dan
    0

    Wow, thanks!  Will let you know how it goes...

  • Dan 1285 posts 3917 karma points c-trib
    Oct 15, 2012 @ 13:49
    Dan
    0

    Hi Lee,

    Many weeks later I'm revisiting this (the original thread was for a personal project which is still on the back-burner) on a 4.9.0 installation.  Did this make it into the most recent version of uComponents, before I create the XSLT extension?

    Thanks

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Oct 15, 2012 @ 14:11
    Lee Kelleher
    0

    Hi Dan,

    Just checked latest uComponents (v5.0) ... and no, sorry, it's not in there. (Only because I'd forgot about it)

    I'll add it in for v5.1 (due for release soon).  In the meantime, might be worth using it as a custom extension.

    Cheers, Lee.

  • Dan 1285 posts 3917 karma points c-trib
    Oct 15, 2012 @ 14:21
    Dan
    0

    No, probs, just thought it was worth checking.  Thanks.

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Oct 15, 2012 @ 14:30
    Lee Kelleher
    1

    Just added it in for v5.1 ... thought best to do it now, otherwise I'd forget (again!) ;-)

Please Sign in or register to post replies

Write your reply to:

Draft