Vim Tips Wiki
Register
Advertisement
Tip 1148 Printable Monobook Previous Next

created 2006 · complexity intermediate · author Salman Halim · version 7.0


Vim 7 has a built-in function called sort() that takes a List and an optional comparator. It works really well, but unlike the Vim 7 command :sort, there is no way to have the function remove duplicates from the list. Hence, this function:

" Works like sort(), optionally taking in a comparator (just like the
" original), except that duplicate entries will be removed.
function! SortUnique( list, ... )
  let dictionary = {}
  for i in a:list
    execute "let dictionary[ '" . i . "' ] = ''"
  endfor
  let result = []
  if ( exists( 'a:1' ) )
    let result = sort( keys( dictionary ), a:1 )
  else
    let result = sort( keys( dictionary ) )
  endif
  return result
endfunction

Call it just like you would sort(). Note that because it removes duplicate entries, the return List isn't necessarily going to be the same size as the original. Furthermore, unlike sort(), this can't do things in place. To replace the original List, do this:

let theList = SortUnique( theList )

References[]

See also[]

Comments[]

This implementation loose the initial type of the list elements when it transforms them into strings. Is see two possible corrections:

  • one that first applies the sort(), and then implements the unique by hand
    • pro: it may be the fastest solution if there aren't many redundant elements
function! list#unique_sort2(list, ...)
  let list = copy(a:list)
  if ( exists( 'a:1' ) )
    call sort(list, a:1 )
  else
    call sort(list)
  endif
  if len(list) <= 1 | return list | endif
  let result = [ list[0] ]
  let last = list[0]
  let i = 1
  while i < len(list)
    if last != list[i]
      call add(result, list[i])
    endif
    let last = list[i]
    let i += 1
  endwhile
  return result
endfunction

  • one that fixes previous code
    • pro: it should be the fastest solution if there are many redundant elements.
function! list#unique_sort(list, ...)
  let dictionary = {}
  for i in a:list
    let dictionary[string(i)] = i
  endfor
  let result = []
  if ( exists( 'a:1' ) )
    let result = sort( values( dictionary ), a:1 )
  else
    let result = sort( values( dictionary ) )
  endif
  return result
endfunction

NB: This function should also receive another (optional) parameter than defines what being equal means.

--Luc Hermitte 16:54, 23 April 2008 (UTC)


Advertisement