mirror of
https://github.com/neovim/neovim.git
synced 2026-04-05 07:09:23 +00:00
feat(lua): add Iter:unique() (#37592)
This commit is contained in:
@@ -1824,9 +1824,11 @@ vim.list.unique({t}, {key}) *vim.list.unique()*
|
|||||||
Only the first occurrence of each value is kept. The operation is
|
Only the first occurrence of each value is kept. The operation is
|
||||||
performed in-place and the input table is modified.
|
performed in-place and the input table is modified.
|
||||||
|
|
||||||
Accepts an optional `key` argument that if provided is called for each
|
Accepts an optional `key` argument, which if provided is called for each
|
||||||
value in the list to compute a hash key for uniqueness comparison. This is
|
value in the list to compute a hash key for uniqueness comparison. This is
|
||||||
useful for deduplicating table values or complex objects.
|
useful for deduplicating table values or complex objects. If `key` returns
|
||||||
|
`nil` for a value, that value will be considered unique, even if multiple
|
||||||
|
values return `nil`.
|
||||||
|
|
||||||
Example: >lua
|
Example: >lua
|
||||||
|
|
||||||
@@ -1847,6 +1849,9 @@ vim.list.unique({t}, {key}) *vim.list.unique()*
|
|||||||
Return: ~
|
Return: ~
|
||||||
(`any[]`) The deduplicated list
|
(`any[]`) The deduplicated list
|
||||||
|
|
||||||
|
See also: ~
|
||||||
|
• |Iter:unique()|
|
||||||
|
|
||||||
vim.list_contains({t}, {value}) *vim.list_contains()*
|
vim.list_contains({t}, {value}) *vim.list_contains()*
|
||||||
Checks if a list-like table (integer keys without gaps) contains `value`.
|
Checks if a list-like table (integer keys without gaps) contains `value`.
|
||||||
|
|
||||||
@@ -3366,6 +3371,43 @@ Iter:totable() *Iter:totable()*
|
|||||||
Return: ~
|
Return: ~
|
||||||
(`table`)
|
(`table`)
|
||||||
|
|
||||||
|
Iter:unique({key}) *Iter:unique()*
|
||||||
|
Removes duplicate values from an iterator pipeline.
|
||||||
|
|
||||||
|
Only the first occurrence of each value is kept.
|
||||||
|
|
||||||
|
Accepts an optional `key` argument, which if provided is called for each
|
||||||
|
value in the iterator to compute a hash key for uniqueness comparison.
|
||||||
|
This is useful for deduplicating table values or complex objects. If `key`
|
||||||
|
returns `nil` for a value, that value will be considered unique, even if
|
||||||
|
multiple values return `nil`.
|
||||||
|
|
||||||
|
If a function-based iterator returns multiple arguments, uniqueness is
|
||||||
|
checked based on the first return value. To change this behavior, specify
|
||||||
|
`key`.
|
||||||
|
|
||||||
|
Examples: >lua
|
||||||
|
vim.iter({ 1, 2, 2, 3, 2 }):unique():totable()
|
||||||
|
-- { 1, 2, 3 }
|
||||||
|
|
||||||
|
vim.iter({ {id=1}, {id=2}, {id=1} })
|
||||||
|
:unique(function(x)
|
||||||
|
return x.id
|
||||||
|
end)
|
||||||
|
:totable()
|
||||||
|
-- { {id=1}, {id=2} }
|
||||||
|
<
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
• {key} (`fun(...):any?`) Optional hash function to determine
|
||||||
|
uniqueness of values.
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
(`Iter`)
|
||||||
|
|
||||||
|
See also: ~
|
||||||
|
• |vim.list.unique()|
|
||||||
|
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
Lua module: vim.json *vim.json*
|
Lua module: vim.json *vim.json*
|
||||||
|
|||||||
@@ -318,7 +318,8 @@ LUA
|
|||||||
• |vim.version.intersect()| computes intersection of two version ranges.
|
• |vim.version.intersect()| computes intersection of two version ranges.
|
||||||
• |Iter:take()| and |Iter:skip()| now optionally accept predicates.
|
• |Iter:take()| and |Iter:skip()| now optionally accept predicates.
|
||||||
• Built-in plugin manager |vim.pack|
|
• Built-in plugin manager |vim.pack|
|
||||||
• |vim.list.unique()| to deduplicate lists.
|
• |vim.list.unique()| and |Iter:unique()| to deduplicate lists and iterators,
|
||||||
|
respectively.
|
||||||
• |vim.list.bisect()| for binary search.
|
• |vim.list.bisect()| for binary search.
|
||||||
• Experimental `vim.pos` and `vim.range` for Position/Range abstraction.
|
• Experimental `vim.pos` and `vim.range` for Position/Range abstraction.
|
||||||
• |vim.json.encode()| has an `indent` option for pretty-formatting.
|
• |vim.json.encode()| has an `indent` option for pretty-formatting.
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ end
|
|||||||
|
|
||||||
--- @return string[]
|
--- @return string[]
|
||||||
local function get_client_names()
|
local function get_client_names()
|
||||||
local client_names = vim
|
return vim
|
||||||
.iter(lsp.get_clients())
|
.iter(lsp.get_clients())
|
||||||
:map(function(client)
|
:map(function(client)
|
||||||
return client.name
|
return client.name
|
||||||
end)
|
end)
|
||||||
|
:unique()
|
||||||
:totable()
|
:totable()
|
||||||
return vim.list.unique(client_names)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @return string[]
|
--- @return string[]
|
||||||
@@ -34,7 +34,8 @@ local function get_config_names()
|
|||||||
vim.list_extend(config_names, vim.tbl_keys(lsp.config._configs))
|
vim.list_extend(config_names, vim.tbl_keys(lsp.config._configs))
|
||||||
|
|
||||||
return vim
|
return vim
|
||||||
.iter(vim.list.unique(config_names))
|
.iter(config_names)
|
||||||
|
:unique()
|
||||||
--- @param name string
|
--- @param name string
|
||||||
:filter(function(name)
|
:filter(function(name)
|
||||||
return name ~= '*'
|
return name ~= '*'
|
||||||
|
|||||||
@@ -365,9 +365,11 @@ end
|
|||||||
--- Only the first occurrence of each value is kept.
|
--- Only the first occurrence of each value is kept.
|
||||||
--- The operation is performed in-place and the input table is modified.
|
--- The operation is performed in-place and the input table is modified.
|
||||||
---
|
---
|
||||||
--- Accepts an optional `key` argument that if provided is called for each
|
--- Accepts an optional `key` argument, which if provided is called for each
|
||||||
--- value in the list to compute a hash key for uniqueness comparison.
|
--- value in the list to compute a hash key for uniqueness comparison.
|
||||||
--- This is useful for deduplicating table values or complex objects.
|
--- This is useful for deduplicating table values or complex objects.
|
||||||
|
--- If `key` returns `nil` for a value, that value will be considered unique,
|
||||||
|
--- even if multiple values return `nil`.
|
||||||
---
|
---
|
||||||
--- Example:
|
--- Example:
|
||||||
--- ```lua
|
--- ```lua
|
||||||
@@ -385,6 +387,7 @@ end
|
|||||||
--- @param t T[]
|
--- @param t T[]
|
||||||
--- @param key? fun(x: T): any Optional hash function to determine uniqueness of values
|
--- @param key? fun(x: T): any Optional hash function to determine uniqueness of values
|
||||||
--- @return T[] : The deduplicated list
|
--- @return T[] : The deduplicated list
|
||||||
|
--- @see |Iter:unique()|
|
||||||
function vim.list.unique(t, key)
|
function vim.list.unique(t, key)
|
||||||
vim.validate('t', t, 'table')
|
vim.validate('t', t, 'table')
|
||||||
local seen = {} --- @type table<any,boolean>
|
local seen = {} --- @type table<any,boolean>
|
||||||
|
|||||||
@@ -213,6 +213,57 @@ function ArrayIter:filter(f)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Removes duplicate values from an iterator pipeline.
|
||||||
|
---
|
||||||
|
--- Only the first occurrence of each value is kept.
|
||||||
|
---
|
||||||
|
--- Accepts an optional `key` argument, which if provided is called for each
|
||||||
|
--- value in the iterator to compute a hash key for uniqueness comparison. This is
|
||||||
|
--- useful for deduplicating table values or complex objects.
|
||||||
|
--- If `key` returns `nil` for a value, that value will be considered unique,
|
||||||
|
--- even if multiple values return `nil`.
|
||||||
|
---
|
||||||
|
--- If a function-based iterator returns multiple arguments, uniqueness is
|
||||||
|
--- checked based on the first return value. To change this behavior, specify
|
||||||
|
--- `key`.
|
||||||
|
---
|
||||||
|
--- Examples:
|
||||||
|
---
|
||||||
|
--- ```lua
|
||||||
|
--- vim.iter({ 1, 2, 2, 3, 2 }):unique():totable()
|
||||||
|
--- -- { 1, 2, 3 }
|
||||||
|
---
|
||||||
|
--- vim.iter({ {id=1}, {id=2}, {id=1} })
|
||||||
|
--- :unique(function(x)
|
||||||
|
--- return x.id
|
||||||
|
--- end)
|
||||||
|
--- :totable()
|
||||||
|
--- -- { {id=1}, {id=2} }
|
||||||
|
--- ```
|
||||||
|
---
|
||||||
|
---@param key? fun(...):any Optional hash function to determine uniqueness of values.
|
||||||
|
---@return Iter
|
||||||
|
---@see |vim.list.unique()|
|
||||||
|
function Iter:unique(key)
|
||||||
|
local seen = {} --- @type table<any,boolean>
|
||||||
|
|
||||||
|
key = key or function(a)
|
||||||
|
return a
|
||||||
|
end
|
||||||
|
|
||||||
|
return self:filter(function(...)
|
||||||
|
local hash = key(...)
|
||||||
|
if hash == nil then
|
||||||
|
return true
|
||||||
|
elseif not seen[hash] then
|
||||||
|
seen[hash] = true
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
--- Flattens a |list-iterator|, un-nesting nested values up to the given {depth}.
|
--- Flattens a |list-iterator|, un-nesting nested values up to the given {depth}.
|
||||||
--- Errors if it attempts to flatten a dict-like value.
|
--- Errors if it attempts to flatten a dict-like value.
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -581,6 +581,23 @@ describe('vim.iter', function()
|
|||||||
matches(flat_err, pcall_err(nested_non_lists.flatten, nested_non_lists, math.huge))
|
matches(flat_err, pcall_err(nested_non_lists.flatten, nested_non_lists, math.huge))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('unique()', function()
|
||||||
|
eq({ 1, 2, 3, 4, 5 }, vim.iter({ 1, 2, 2, 3, 4, 4, 5 }):unique():totable())
|
||||||
|
eq(
|
||||||
|
{ 1, 2, 3, 4, 5 },
|
||||||
|
vim.iter({ 1, 2, 3, 4, 4, 5, 1, 2, 3, 2, 1, 2, 3, 4, 5 }):unique():totable()
|
||||||
|
)
|
||||||
|
eq(
|
||||||
|
{ { 1 }, { 2 }, { 3 } },
|
||||||
|
vim
|
||||||
|
.iter({ { 1 }, { 1 }, { 2 }, { 2 }, { 3 }, { 3 } })
|
||||||
|
:unique(function(x)
|
||||||
|
return x[1]
|
||||||
|
end)
|
||||||
|
:totable()
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
it('handles map-like tables', function()
|
it('handles map-like tables', function()
|
||||||
local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v)
|
local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v)
|
||||||
if v % 2 ~= 0 then
|
if v % 2 ~= 0 then
|
||||||
|
|||||||
Reference in New Issue
Block a user