zsh-users
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh Users <zsh-users@sunsite.dk>
Subject: Re: Sorting file names randomly
Date: Sun, 24 Jul 2005 06:44:15 +0000	[thread overview]
Message-ID: <1050724064415.ZM20425@candle.brasslantern.com> (raw)
In-Reply-To: <20050723194240.GA32416@DervishD>
In-Reply-To: <20050723212657.GA744@DervishD>

On Jul 23,  9:42pm, DervishD wrote:
}
}     shuffle dir1/* dir2/* ...

There's no reason to noglob and alias this.  The space required to expand
the glob on the command line is no worse than what you're doing inside
the function anyway, and there aren't argument-size limits on calls to
shell functions, only on external commands.

}     I've tried to use '$~' in the solution above (the '%0...' one),
} but it doesn't work because although files in dir1 and files in dir2
} are sorted randomly, dir1 files appear always before dir2 files. It
} seems that the random number doesn't affect the sorting of pathnames

Right, (e:..:) is applied to the base file name, within each directory,
not to the entire string being globbed.

}     Any simple way of using the above solution for this new problem

Not really; glob qualifiers aren't going to do it for you.

} Any simple way of doing the random sort on a group of patterns?

You'll have to first expand them and then sort the resulting array.

On Jul 23, 11:26pm, DervishD wrote:
}
}     The function returns the list in the 'reply' array parameter, and
} prints it on stdout.
} 
}     If anybody can make it better/shorter, suggestions are welcome ;)

The following won't work in versions of zsh that lack the += assignment:

    function shuffle {
      emulate -L zsh
      integer i
      reply=()
      # set -- $~*   # uncomment to use with noglob alias
      for ((i=1; i <= $#; ++i)) { reply[i*RANDOM/32768+1]+=($argv[i]) }
      shift reply
      print -l $reply
    }

The use of array[index]+=(list) means we can insert stuff into the middle
of the array without replacing the stuff that's there.  This has the side
effect that array[1] is always empty (because we always append things
after it), which is why the shift is needed.

So this is a true shuffle; for each "card" $argv[i], we insert it into
the reply "deck" at a random position among the previous i-1 cards.

A more efficient way might be this:

    function shuffle {
      emulate -L zsh
      declare -A h
      local +h -Z 5 RANDOM=$SECONDS
      integer i
      # set -- $~*   # uncomment to use with noglob alias
      for ((i=1; i <= $#; ++i)) { h[$i.$RANDOM]=$argv[i] }
      reply=( $h )
      print -l $reply
    }

This creates random but unique hash keys and then retrieves the shuffled
values in one assignment; we don't care that the order of hash values is
indeterminate, because we want it to be random!  The local RANDOM is
there to force it to be zero-padded to 5 places, so all the hash keys
are the same length; probably not essential.

(Incidentally, I didn't test this, but I'll bet that "seeding" a local
RANDOM like that ruins the repeatable sequence of the global RANDOM.)

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


  reply	other threads:[~2005-07-24  6:44 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-07-23 19:42 DervishD
2005-07-23 21:26 ` DervishD
2005-07-24  6:44   ` Bart Schaefer [this message]
2005-07-24  7:39     ` DervishD
2005-07-24  8:37     ` DervishD
2005-07-24  8:40       ` DervishD
2005-07-24 10:32         ` Bart Schaefer
2005-07-25  6:47           ` Bart Schaefer
2005-07-25 13:15           ` DervishD
2005-07-25 13:27           ` DervishD
2005-07-25 17:46             ` Bart Schaefer
2005-07-25 18:10               ` DervishD
2007-11-19  4:21     ` Clint Adams
2007-11-19  8:57       ` Bart Schaefer
2007-11-19  9:08         ` Bart Schaefer
2007-11-19 11:44         ` Clint Adams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1050724064415.ZM20425@candle.brasslantern.com \
    --to=schaefer@brasslantern.com \
    --cc=zsh-users@sunsite.dk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).