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 10:32:13 +0000	[thread overview]
Message-ID: <1050724103213.ZM20780@candle.brasslantern.com> (raw)
In-Reply-To: <20050724073914.GA2665@DervishD>
In-Reply-To: <20050724083732.GA73@DervishD>
In-Reply-To: <20050724084014.GA86@DervishD>

On Jul 24,  9:39am, DervishD wrote:
}
} >       for ((i=1; i <= $#; ++i)) { reply[i*RANDOM/32768+1]+=($argv[i]) }
} 
}     Why is it better than my function?

It's shorter (which is one of the things you asked for), and it only
does array processing rather than building up and tearing down strings.

} Maybe this is faster than doing the '(e' thing?

More on this below.

} >       for ((i=1; i <= $#; ++i)) { h[$i.$RANDOM]=$argv[i] }
} 
}     I understand this one better ;) That's another solution I thought
} of, but I assumed that if I used associative arrays, the order of
} elements would be the order in which they were inserted (which is
} not, I've discovered right now).
} 
}     Anyway, the ordering of elements in an associative array is not
} very random if $RANDOM is not included in the key, and I don't
} understand it :?? How are associative arrays elements sorted?

Are you familiar with the concept of hash tables?  That's how nearly
all languages that have associative arrays, implement them, and in
many cases (e.g. Perl) they're even called "hashes" by the language.

You can think of the elements as being ordered by a set of numbers
computed by applying a simple algorithm to the ascii values of the
characters in the key strings.  It's actually a bit more complex than
that, but close enough.

On Jul 24, 10:37am, DervishD wrote:
}
}     How about this?:

Well ...

} function shuffle () {
} 
}     setopt nullglob globdots rcexpandparam
}     
}     reply=()
}     reply=($*)

Don't you mean $~* there?  Otherwise you have the problem with
multiple directories that you alluded to once before.

}     reply=($reply(e:'REPLY="${(l.5..0.)RANDOM} $REPLY"':))

This is wasteful in a number of ways.

First, the (l.5..0.) is just left-zero-padding $RANDOM, so rather than
force the shell parse that and work out what to do once for every file
name, it would be better to declare "local +h -Z 5 RANDOM" as I did.
(Just remember to seed RANDOM when making it local.)

Second, by using a glob qualifier, you're forcing the shell to stat()
every file name second time, after it has already been done once when
reply=($~*) is assigned [assuming $~* is what you meant].

Third, you're doing string concatenation, adding six bytes for each
file name.  If you're worried about exceeding argument limits, you
ought to be worried about how much extra memory that eats.

Fourth, you've eventually got to do this ...

}     reply=(${reply/#????? /})

... which has to copy every string in order to pattern-match it and
chop it up before assigning it back again, so you're roughly doubling
the memory needed right there, possibly as much as tripling it if I
recall correctly how array assignments are performed.

My hash solution isn't very much less memory intensive (if you skipped
the final assignment to the reply array and just printed the values it
would be better); but the += version is about as small a footprint as
you're going to get, because inserting array slices only copies the new
elements being inserted (everything else is moving of pointers to the
existing elements).

}     print -l $reply
} 
}     return 0

Unless you expect "print" to fail, the "return 0" is redundant.

}     It does the globbing outside, and shuffles correctly. Any way of
} making the 'reply' assignments shorter?

You can eliminate the glob qualifier by using the "eval" trick I posted
on a different thread (placement of quotes and spaces is important):

eval 'reply=(' '$RANDOM '${(q)reply} ')'

However, you can't do fewer than three assignments.

On Jul 24, 10:40am, DervishD wrote:
} 
} >     reply=($*)
} >     reply=($reply(e:'REPLY="${(l.5..0.)RANDOM} $REPLY"':))
} >     reply=(${(o)reply})
} 
}     How could I avoid doing this? I cannot put the 'o' in the
} assignment above this one because it doesn't work, it seems to sort
} *before* applying the 'e' glob modifier).

Obviously the glob applies after any sorting in that second assignment.
The glob qualifier is being applied to the strings that *result* from
the parameter expansion; that's why you need the rcexpandparam option.


  reply	other threads:[~2005-07-24 10:32 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
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 [this message]
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=1050724103213.ZM20780@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).