如何在vim中打乱列表?
Posted
技术标签:
【中文标题】如何在vim中打乱列表?【英文标题】:How to shuffle a list in vim? 【发布时间】:2013-07-12 15:45:07 【问题描述】:在 Vim 中打乱列表的最佳方法是什么?
我正在尝试对 vim 中的行进行随机排序(使用 vimscript)。 我为此创建了一个包含所有行号的列表(在我的选择中)。
p.e.如果我从第 10 行到第 20 行中选择,我的列表将是:
mylist = ['10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20']
我想对这些行进行随机排序,并使用 for 循环将它们放回新序列中的相同选择中。 为了实现这一点,我想多次洗牌,但不知道如何洗牌。
另一种解决方案是从我的最后一个随机选择一个索引。
找不到最好的方法。
我知道我可以使用 python、ruby 或其他语言对行进行排序,但我不想安装它们。 我想使用 vimscript 实现上述。
【问题讨论】:
有用:Native Vim Random number script。我看到你已经知道那里的算法了。 对于 Vim 脚本中更重量级的随机数生成器,还有Rndm。 我昨天检查了本机 Vim 随机脚本,但发现这些值不是随机创建的(请参阅我在该页面上的评论)。我还检查了 Chip Campbell 的 Rndm 脚本,但发现排序也不是随机的(除此之外,还有很多代码) 【参考方案1】:您可以使用“UNIX 风格”并使用 coreutils
包中的 shuf
命令:
:10,20!shuf<CR>
【讨论】:
我选择的武器::'<,'>!sort -R
,或者使用rl
from randomize-lines
@sehe,谢谢您的回复。 sort! -R
在我看来不是一个很好的随机排序(这是我之前的随机排序命令)。 rl
在我的电脑上不起作用。什么都没有发生。
@Remonn 对于为什么:!sort -R
不能进行良好的随机排序,您有什么实质性的主张吗?由于我只是比较了 sort.c 和 shuf.c 实现,因此我不得不稍微让 sort.c 更加通用(例如尝试sort -uR
,或使用特定的键)。
perl -M"List::Util qw(shuffle)" -e "print shuffle <>" input.txt > output.txt
【参考方案2】:
截至 2019 年的更新:
osx 现在在排序中包含一个-R
标志,因此您应该可以使用
:'<,'>!sort -R
=== 上一个答案:===
Sort 在 osx 中没有 -R 标志,所以:
brew install coreutils
在 vim 中选择行,然后运行:
:'<,'>!gsort -R
【讨论】:
从 2019 年开始,sort 在 macOS 中带有 -R 标志,因此不再需要使用 gsort。 我在linux上使用:%!sort -R
【参考方案3】:
如果你需要一个统一的随机数生成器,我不知道 vim 是否可以为你提供一个原生的(或者你可以求助于一些插件)。但是,如果你只是想打破一些行的顺序,你可以试试这个功能:
function! Random()
return reltimestr(reltime())[-2:]
endfunction
上面的函数以毫秒为单位返回当前时间戳的最后两位数。
换行,你可以(例如整个缓冲区)
%s/^/\=Random() . " "
然后
:sor n
最后删除添加的前缀:
%s/^\S* //
你当然可以用<bar>
链接上面的命令。
%s/^/\=Random() . " "/|sor n|%s/^\S* //
或者不创建函数,在:s
中写入随机数部分:
%s/^/\=reltimestr(reltime())[-2:] . " "/|sor n|%s/^\S* //
如果我测试 30 行值为 1-30(由seq 30
生成),
第一次结果是:
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
第二次结果:
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
希望对你有帮助
【讨论】:
非常感谢肯特。我注意到它每 8、9、10 行对行进行分组。也可以在这里查看我的评论:***.com/q/12737977 我最终决定使用shuf
命令(我已经安装了 cygwin),即使我更喜欢只使用 vimscript。这也搜索一个随机值,非常好exe 'normal! '.(system('sh -c "echo -n $RANDOM"') % 1000)
,但是对每一行执行此操作都会连续闪烁我的 VIM 窗口(使用 bash shell)
我发布了答案,假设您没有可用的外部 shuf、sort 或 shell $RANDOM
变量。如果如你所说,你有这些东西,shuf
将是最直接的方法,我也会这样做。我的命令是一种解决方法。
而且,我看不到it groups lines every 8,9,10 lines
,您可以在我的答案中查看两次运行的结果。我检查了另一个问题和答案,我们的想法相同,但取的数字不同。
肯特,也许我和你一样使用另一个时间标准?在我的电脑上测试时,我清楚地看到了一组线条。【参考方案4】:
你可以编写一个 python 脚本来帮助 vim 中的随机。
我创建了一个名为pyrandom.py
的python 文件。然后添加执行模式chmod +x pyrandom.py
,最后就是将pyrandom.py
的目录添加到PATH
,可以暂时运行export PATH=$PATH:/directory/to/pyrandom.py/
添加到PATH
。
现在,您在 vim 中选择行,然后运行: :'!pyrandom.py
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
【讨论】:
以上是关于如何在vim中打乱列表?的主要内容,如果未能解决你的问题,请参考以下文章
Python面试必考重点之列表,元组和字典第四关——编写一个函数(不要使用python模块的函数),打乱列表元素的顺序/如何对列表元素进行随机排列