How to shuffle a list in vim?

12,639

Solution 1

You could go "UNIX style" and use the shuf command from the coreutils package:

:10,20!shuf<CR>

Solution 2

UPDATE as of 2019:

osx now includes a -R flag in sort, so you should be able to just use

:'<,'>!sort -R

=== Previous answer: ===

Sort does not have a -R flag in osx, so:

brew install coreutils

select lines in vim, and run:

:'<,'>!gsort -R

Solution 3

if you need a uniformed random number generator, I don't know if vim could provide you one native (or you could turn to some plugins). however, if you just want to break some order of a number of lines, you could try this function:

function! Random()
    return reltimestr(reltime())[-2:]
endfunction

the function above return the last two digits of current timestamp in ms.

to shuf lines, you could (for example the whole buffer)

%s/^/\=Random() . " "

then

:sor n

finally remove added prefix:

%s/^\S* //

You could of course chain the commands above with <bar>.

%s/^/\=Random() . " "/|sor n|%s/^\S* //

or without creating the function, write the random number part in your :s :

%s/^/\=reltimestr(reltime())[-2:] . " "/|sor n|%s/^\S* //

If I test 30 lines with value 1-30 (generated by seq 30),

first time result was:

2
26
12
17
8
22
27
3
13
18
23
9
28
4
14
19
1
24
10
29
5
6
15
20
25
30
11
16
7
21

2nd time result:

4
22
25
28
6
9
18
12
15
1
3
5
21
24
27
30
8
11
17
14
2
20
23
26
29
7
10
16
13
19

hope it helps

Solution 4

you can write a python script to help random in vim. I create a python file named pyrandom.py. then add the execution mode, chmod +x pyrandom.py, last thing you need is adding the directory of the pyrandom.py to PATH, you can run export PATH=$PATH:/directory/to/pyrandom.py/ temporarily to add to PATH.

now, you select lines in vim, and run: :'<,'>!pyrandom.py

the content in pyrandom.py

#!/usr/bin/python
import sys
import random

all_lines = []
for line in sys.stdin:
    all_lines.append(line.rstrip('\n'))

random.shuffle(all_lines)

for line in all_lines:
    print line
Share:
12,639
Reman
Author by

Reman

Updated on June 24, 2022

Comments

  • Reman
    Reman almost 2 years

    What is the best way to shuffle a list in Vim?

    I'm trying to randomly sort lines in vim (using vimscript). I created for this a list with all line numbers (in my selection).

    p.e. if I select from line 10 to 20 my list will be:

    mylist = ['10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20']
    

    I would like to sort the lines randomly and with a for loop put them back in the same selection in the new sequence. In order to realize this I would like to shuffle the list many times but don't know how to shuffle the list.

    Another solution would be to pick an index from my last randomly.

    Can't find out what is the best way.

    I know I can sort lines using python, ruby or with other languages but I don't want to install them. I would like to realize above using vimscript.

  • sehe
    sehe almost 11 years
    My weapon of choice: :'<,'>!sort -R, or use rl from randomize-lines
  • Reman
    Reman almost 11 years
    Thank you very much Kent. I noted that it groups lines every 8,9,10 lines. See also my comment here: stackoverflow.com/q/12737977 I finally decided to use the shuf command (I already have cygwin installed) even if I prefer to use only vimscript. This one search a random value as well and is very nice exe 'normal! '.(system('sh -c "echo -n $RANDOM"') % 1000) but doing this for every line it flickers my VIM window continuously (using the bash shell)
  • Reman
    Reman almost 11 years
    @sehe, Thank you for your reply. sort! -R does in my opinion not a very good random sort (This was my previous sorting randomly command). rl doesn't work on my pc. Nothing happens.
  • Kent
    Kent almost 11 years
    I posted the answer, assume you don't have external shuf, sort or the shell $RANDOM variable available. if as you said, you have those stuff, shuf would be the most straightforward way, I would go this way as well. My command is kind of workaround.
  • Kent
    Kent almost 11 years
    and, I cannot see it groups lines every 8,9,10 lines you can checkout the result of two runs in my answer. I checked the other question and answer, we got same idea, but taking the different numbers.
  • sehe
    sehe almost 11 years
    @Remonn Have you got any substantial claim as to why :!sort -R doesn't do a good random sort? Since I just compared sort.c and shuf.c implementations, and have to give a slight edge to sort.c for being just more versatile (e.g. try sort -uR, or using a specific key).
  • Reman
    Reman almost 11 years
    Kent, maybe I'm using another time standard as you do? I clearly see a grouping of lines when I test it on my pc.
  • Alexander Farber
    Alexander Farber about 9 years
    perl -M"List::Util qw(shuffle)" -e "print shuffle <>" input.txt > output.txt
  • take
    take over 5 years
    As of 2019, sort has a -R flag in macOS, so it is no longer necessary to use gsort.
  • Edgard Leal
    Edgard Leal about 3 years
    I used :%!sort -R on linux