How to randomly select each item at a time from a list, without repeating the item?

I have a list of URLs in a text file.

Screenshot 2024-09-09 at 09.25.10

In the screenshot, the list contains 5 list items.

I want to select an item at random in such a way:

  1. that I want to perform actions on every item in the list (exhausting the entire list) one by one, without the macro randomly selecting the same item again
  2. that I want to perform actions only on few items in the list one by one, without the macro randomly selecting the same item again. For example, I want to perform actions on only 3 items one by one, out of the list of 5 items.

Also, I need control over customising the set of actions for each item. There are two ways (need both ways):

  1. Need to able to specify if the randomly selected item is x, then perform y set of actions. For example (with respect to the screenshot), if the randomly selected item is facebook.com, then open the URL. If the randomly selected item is youtube.com, then display the text in a pop up.
  2. Need to be able to specify if the item is selected at random for the first time (during the current execution of the macro), perform x set of actions, if the item is selected at random for the second time, perform y set of actions, if the item is selected at random for the third time, perform z set of actions and so on. For example (with respect to the screenshot), for randomly selected first URL (any URL), open the URL in Safari. For the second URL, speak the URL text. For the third URL, display the URL text in a pop up.

I would like to help. But there are so many ambiguities. For example, you don't say when this program stops. And again, you say, "perform x set of actions" but you don't even say what those actions are. How can I wrote code if I don't know what you want? You should specify every action if you want me to code anything.

Personally, I think it would help if you explain your real goals here. I think I'm lost in the weeds, when I really need a description of the forest to be able to help. Nevertheless I did take a stab at it, and here's my code that does SOME, but not ALL, of what you asked for. I might take another stab if you clarify some of your requirements.

I didn't even test this code, because there's no point in testing something that I know is not adequate.

Test Macro Macro (v11.0.3)

Test Macro.kmmacros (8.1 KB)

I didn't realise that. Sorry. i am not a programmer so may be that is why i failed to realise how much in depth information is needed.

The program (or the macro) may have multiple actions before and after the workflow we are discussing here, which may not be related to the workflow.
When I said 'perform x set of actions' I simply meant getting the output of randomly selected URL from the list and me having the ability to perform any actions I want, rather than putting each URL in the same loop of set of actions. I'll give you an example of such a loop. Please refer the screenshot. This is what I am currently using.

Here, same set of actions are performed on each URL. Also, the URLs are not selected at random i.e. if we execute the actions shown in the screenshot, then for each execution, URLs would be chosen in the same order. I want to choose URLs in random order.

Also, in the given screenshot, the set of actions are performed on ALL URLs enlisted in the selected file. What if I want to perform the set of action only on specific number of URLs?

Also the set of actions shown in the screenshot might be different depending upon my use case.

P.S. I know I have not re-explained all 4 points from the original post in this reply of mine, but whatever I have mentioned in this reply is a top priority for me and might explain remaining points some later day or create a fresh post altogether. But if in case this reply clears any ambiguity you had for remaining points then i am always happy to receive your response to those.

Also, here is the file chosen in the screnshot:
Screenshot 2024-09-09 at 11.56.30

Oh. I didn't know you wanted the output of the URL. Why do you want the output? (Even your sample code didn't fetch the output, or do anything with the output.) The output will be in the HTML language, which might be extremely difficult for a macro to parse. Perhaps you should tell us why you want the HTML. What are you trying to do with it? Are you familiar with the HTML language? Do you know how difficult it is to get text from it? What is your end goal with the output? Even in your newest post, you haven't described what the "actions" you want to do are. The actions you want may require a different solution for each website you want to access.

The code I provided did give you a solution for one part of your problem, which was sorting the source URLs into a random order. Did you understand my macro?

Hi, @fluid_eye. I'm not sure I completely understand your objective, but for the first portion, this should work:

Download: Random Subset of Urls.kmmacros (4.0 KB)

Macro-Image


Macro-Notes
  • Macros are always disabled when imported into the Keyboard Maestro Editor.
    • The user must ensure the macro is enabled.
    • The user must also ensure the macro's parent macro-group is enabled.

System Information
  • macOS 14.6.1 (23G93)
  • Keyboard Maestro v11.0.3

@Airy :sweat_smile: I didn't know 'output of URL' have some meaning in technical language. I didn't mean that kinda output. After I bumped into this post, i started realising what your macro is about. I have one question for you.


what does this action do from your macro?

@_jims :raising_hand_man: hello, nice to see you again. I remember you from your expertise in apple shortcuts. Thanks for your input. It gave me error when I tried the macro you shared. Here's the screenshot of the error:
Screenshot 2024-09-10 at 12.35.15

Apparently I seem to be able to imagine a solution now. I bumped into this post and figured out a way to randomise the order (see the screenshot below).

Following is the only point I am yet to find answer to. May be some another time, with a fresh post as my problem has been solved temporarily.

Here’s a versjon of @_jims’ macro, using native KM-actions only, that might work for you

Random Subset of Urls [version using native KM-actions only].kmmacros (18 KB)

2 Likes

Nice work, @Alexander!

It appears that you have not upgraded to Keyboard Maestro v11+ which supports JavaScript modern syntax. Since @Alexander has provided a nice native solution, I suggest you go with that.

1 Like

Thanks for chipping in. I tried your macro, gave a little error.

Screenshot 2024-09-10 at 18.21.02

Sorry, I'm not understanding your objective, @fluid_eye. Maybe share using pseudocode.

If you want to use the logic @Alexander provided, try disabling the action with the %Delete%.

But now that I look more carefully, @Alexander's logic differs from mine. The native actions pick local__count urls from local__urls, but a given url could be repeated. That JXA code that I provided, will select local_Count random urls from the set, but all will be unique.

What version of Keyboard Maestro are you using? I'm using v11.0.3.

Ah, but I believe swaping out the %Delete% action with a Search and Replace searching the variable local_urls for %Variable%local__urls[local__randNumber]\n%\n replacing with nothing, should fix both that and making my macro not requiring KM11. Not by my computer until tonight, otherwise I’d code it up

Edit: Added a \n to the end of the search, as I believe it left blank lines in the local__urls without it

1 Like

For Keyboard Maestro pre-v11, try this:

Download: Random Subset of Urls pre-v11.kmmacros (4.5 KB)

Macro-Image


Macro-Notes
  • Macros are always disabled when imported into the Keyboard Maestro Editor.
    • The user must ensure the macro is enabled.
    • The user must also ensure the macro's parent macro-group is enabled.

System Information
  • macOS 14.6.1 (23G93)
  • Keyboard Maestro v11.0.3

That will take the contents of the variable LocalActions and then sort the lines randomly, then take the first line from the result, then save that line into a variable called LocalActionPicked. I think it may be possible to do these things using native keyboard maestro actions, but it will look about three times as complicated as this solution, so I chose to give you this solution instead.

1 Like

@_jims' newest version will probably serve you well, but just thought I'd upload a version of my approach also that I believe should be pre-KM11-safe.

This version is slightly more robust than the simpler Search and Replace approach proposed in my last post, in that this version won't break if a picked entry is a trailing subset of other entries (as example.com is of subdomain.example.com).

Random Subset of Urls [using native KM-actions only- pre-KM11-safe] v0.3.kmmacros (20 KB)

Macro Image

EDIT: Found a fault in the macro so I re-uploaded it. The fault was that it did not deal as well with duplicated entries (when there where many of them in a row) as I thought. The Until within the Repeat fixes this. But I am starting to think that an initial removal of duplicated lines would be just as sensible.

Not near the manual right now, but wasn't the use of \n for pseudo array access a KM v11 introduction?

1 Like

Aj … I thought it was only setting of array elements that came with KM11 in this regard, but it seems you're right

From The Manual, What's New, KM11.0.1, Engine:

Support \ processing in variable token array item separators (eg %Variable%Lines[3]\n%).


I guess space should be a safe delimiter for lists of URLs(?). Here's a version of the macro that turns the list into a space delimited list before processing:

Random Subset of Urls [using native KM-actions only- pre-KM11-safe] v0.4.kmmacros (21 KB)

Macro Image

Maybe -- but OP is drawing from a text file so there's a chance of trailing space(s) on a line which would lead to empty array elements.

A more general approach is to S'n'R linefeeds for your own, unique-in-the-text, delimiter -- something like ==myKMsep==. And if you are worried that that may not be unique it's easy to write a loop that searches your text and adds extra = front and back of the delimiter until there's no match, then use that "expanded" delimiter.

1 Like

I can't help but think we're making this more complicated than it needs to be :wink:

The easiest way open n sites in a random order is to randomise the list just once then work through the first n items -- there's more work needed for input sanitisation and the prompt than the actual random opening!

For example, for the text file URL List.txt on the Desktop that contains

# Google searches
https://www.google.com/

# YouTube and other video sites
https://www.youtube.com/

# Social Media
https://www.facebook.com/
https://www.instagram.com/
https://www.linkedin.com/

(coz comments and whitespace makes it easier to edit):

Random URLs from list.kmmacros (11.6 KB)

Image

...and using "For Each" over our Collection of lines avoids issues with KM versions and array access tokens, etc.

The first is easy -- change the "Open URL" action for a "Switch/Case" that tests the URL and runs the appropriate branch.

The second is more difficult as it directly conflicts with your earlier

...so the macro will need to be more of the "pick a random line" form, with a count included on each line. Probably better to do this as a separate macro rather than pile on more complexity to the first one.

Could you try your example for this again? You seem to have included the "different actions for different URLs" example in the wrong section, because point 2 needs examples of different actions for the same URL.

1 Like

I can’t help but think that you’re very right in your assumption, and I really like your approach here!

I also like allot the take on safe delimiting with uncertain source data, that you proposed in your prior post! I’ll definitely implement a version of this into many of my coming (and existing) macros!
I guess my take on it would often be to define a single character as a delimiter in a variable, and appending this same character to the variable while the source-data contains this variables value. I guess I in many use cases then, when using this dynamic delimiter approach, would have to resort to process tokens filtering and dynamic variables (with double and triple percentages), but it will be so much better than bending my head around figuring out safe custom delimiters all the time!