Reputation: 8119
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.
Upvotes: 37
Views: 16588
Reputation: 196846
You could go "UNIX style" and use the shuf
command from the coreutils
package:
:10,20!shuf<CR>
Upvotes: 51
Reputation: 10772
osx now includes a -R
flag in sort, so you should be able to just use
:'<,'>!sort -R
Sort does not have a -R flag in osx, so:
brew install coreutils
select lines in vim, and run:
:'<,'>!gsort -R
Upvotes: 21
Reputation: 64
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
Upvotes: 2
Reputation: 195229
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
Upvotes: 4