现在我正在使用 Gvim 在 Windows 上工作。我想要一种不使用操作系统的外部命令的纯 Vim 方式,来计算 Vim 中重复行的重复次数。换句话说,我想要一种像 ":!sort % | uniq -c" 这样的纯 Vim 方式。
没有现成的等价物。下面是一个快速而肮脏的近似值。
正在做:
:echo getline(1,'$')->map({ idx, val -> getline(1,'$')->count(val) .. ' ' .. val })->sort()->uniq()->join("\n")
Run Code Online (Sandbox Code Playgroud)
在这个缓冲区上:
foo
foo
bar
baz
Run Code Online (Sandbox Code Playgroud)
呼应这一点:
1 bar
1 baz
2 foo
Run Code Online (Sandbox Code Playgroud)
在命令行中,这应该提供一个很好的起点。
分解:
:echo {expr}
Run Code Online (Sandbox Code Playgroud)
{expr}回显命令行中的输出。
getline(1,'$')
Run Code Online (Sandbox Code Playgroud)
返回包含缓冲区中每一行的列表。
->map({ idx, val -> getline(1,'$')->count(val) .. ' ' .. val })
Run Code Online (Sandbox Code Playgroud)
将列表中的每一项加上它在列表中的计数。
->sort()
Run Code Online (Sandbox Code Playgroud)
对列表进行排序。
->uniq()
Run Code Online (Sandbox Code Playgroud)
从列表中删除重复项。
->join("\n")
Run Code Online (Sandbox Code Playgroud)
最后将它与换行符作为分隔符连接起来,以便在回显到命令行时看起来不错。
虽然 romainl 的实现完全正确,但使用字典来计算出现次数可能会具有更好的时间复杂度。
:let dict={}
:g/$/let ln=getline(".") | if !has_key(dict, ln) | let dict[ln]=0 | endif | let dict[ln]+=1
:for [k, v] in items(dict) | echo v." ".k | endfor
Run Code Online (Sandbox Code Playgroud)