如何计算 Vim 中重复行的重复次数?

Bre*_*aul 1 vim

现在我正在使用 Gvim 在 Windows 上工作。我想要一种不使用操作系统的外部命令的纯 Vim 方式,来计算 Vim 中重复行的重复次数。换句话说,我想要一种像 ":!sort % | uniq -c" 这样的纯 Vim 方式。

rom*_*inl 5

没有现成的等价物。下面是一个快速而肮脏的近似值。

正在做:

: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)

最后将它与换行符作为分隔符连接起来,以便在回显到命令行时看起来不错。


Arm*_*ali 5

虽然 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)