obsidian-dataview icon indicating copy to clipboard operation
obsidian-dataview copied to clipboard

Random list of pages

Open f6cm opened this issue 4 years ago • 8 comments
trafficstars

I’d like to be able able to view a random list of pages, from a source. Ideally, I would be something like:

´´´dataview LIST FROM #Quotes
SORT RANDOM
LIMIT 5
´´´

Which would output a list of 5 random quotes. I don’t think it’s already possible. Or maybe via dataviewjs ?

Thanks for this amazing plugin and the wonderful job you’re doing!

f6cm avatar Oct 22 '21 18:10 f6cm

The tricky part about this is getting the right level of random - Dataview views internally refresh frequently, and during refreshes you probably don't want to see the list shuffle every time. Should random change every hour? Every day?

I'm planning on implementing this via a random(rowId, duration) function as well as a RANDOMIZE command.

blacksmithgu avatar Oct 23 '21 17:10 blacksmithgu

Good point!

What you suggested is certainly the best implementation, with a RANDOMIZE command and the ability to set a default cache duration. I think it covers all the different needs people may have with this function.

Thanks!

f6cm avatar Oct 24 '21 08:10 f6cm

I came to request this feature, but instead am adding a +1! For a use case, I'm wanting to use this to create a "writing inbox" query that presents me with a random order of things I can work on to avoid getting stuck.

Thank you!

EDIT: In discussing this with @AB1908 on the discord, they cooked up this dataviewjs query that works as a workaround for now. It seems to refresh in legacy editor when switching to reading view, but neither of us can figure out how to force a refresh in Live Preview in a sane way.

function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

var results = dv.pages("#writinginbox or #to/expand")
                    .sort(page => page.file.mtime, "desc");
shuffleArray(results);
dv.table(
  ["File Size", "File"],
  results
    .map(page => [page.file.size, page.file.link])
);

mediapathic avatar Feb 24 '22 10:02 mediapathic

You can force refreshes via dv.index.touch(), for what it's worth. If you also want something that only changes on a specific cadence (every hour, every day), you can use a fixed random seed.

blacksmithgu avatar Feb 24 '22 22:02 blacksmithgu

Just wanted to add that came to add a FR & instead I'm impressed this is already on the docket with even better feature details planned. @blacksmithgu, you're fantastic!

Jahteo avatar Mar 02 '22 02:03 Jahteo

Here's another snippet from @pseudometa:

const limit = 20;
const notes = dv.pages('#seedling')
    .sort(() => 0.5 - Math.random())
    .slice (0, limit)
    .map (note => note.file.link);
dv.list(notes);

From https://discord.com/channels/686053708261228577/840286238928797736/962071289076539453

AB1908 avatar Apr 08 '22 19:04 AB1908

I have been randomly sorting a list of "Favorites" to be used as a "Recommendation List" using the previous comments in this issue. I am not sure how to get it to refresh less frequently though:

const limit = 5;
dv.table(["File", "Director", "Studio", "Genres", "Year"],
	dv.pages('"Reference/Movies"')
		.where(p => p.starred == true)
	    .sort(() => 0.5 - Math.random())
	    .slice(0, limit)
	    .map(p => [p.file.link, p.director, p.studio, p.genre, p.released])
);

Is there a way to change how often it refreshes? Or get it to refresh when you click the table or touch the table?

tahoeschrader avatar Jul 21 '22 21:07 tahoeschrader

I use this

```dataviewjs
let random = (function (a, b, now = Date.now()) {
    let msRefreshRate = 1000*60*60*24
    a = b = (now - (now%(msRefreshRate)));
  return function () {
      a = (a * 67307) & 0xffff;
      b = (b * 67427) & 0xffff;
      return a ^ (b << 15);
  };
})();
let numberOfLinks = 1
dv.table([],
	dv.pages('"watever you want to search"')
	    .sort(() => random() - random())
	    .slice(0, numberOfLinks)
	    .map(p => [p.file.link])
);

pitermarx avatar May 09 '24 12:05 pitermarx