0
0
mirror of https://github.com/vim/vim.git synced 2025-09-04 21:33:48 -04:00

updated for version 7.4.218

Problem:    It's not easy to remove duplicates from a list.
Solution:   Add the uniq() function. (LCD)
This commit is contained in:
Bram Moolenaar 2014-03-25 18:24:23 +01:00
parent 1a3eb8e1b5
commit 327aa02dda
7 changed files with 125 additions and 32 deletions

View File

@ -1650,7 +1650,7 @@ And a few warnings:
7. Sorting text *sorting* 7. Sorting text *sorting*
Vim has a sorting function and a sorting command. The sorting function can be Vim has a sorting function and a sorting command. The sorting function can be
found here: |sort()|. found here: |sort()|, |uniq()|.
*:sor* *:sort* *:sor* *:sort*
:[range]sor[t][!] [i][u][r][n][x][o] [/{pattern}/] :[range]sor[t][!] [i][u][r][n][x][o] [/{pattern}/]

View File

@ -327,6 +327,7 @@ examples: >
Changing the order of items in a list: > Changing the order of items in a list: >
:call sort(list) " sort a list alphabetically :call sort(list) " sort a list alphabetically
:call reverse(list) " reverse the order of items :call reverse(list) " reverse the order of items
:call uniq(sort(list)) " sort and remove duplicates
For loop ~ For loop ~
@ -2005,6 +2006,8 @@ trunc( {expr}) Float truncate Float {expr}
type( {name}) Number type of variable {name} type( {name}) Number type of variable {name}
undofile( {name}) String undo file name for {name} undofile( {name}) String undo file name for {name}
undotree() List undo file tree undotree() List undo file tree
uniq( {list} [, {func} [, {dict}]])
List remove adjacent duplicates from a list
values( {dict}) List values in {dict} values( {dict}) List values in {dict}
virtcol( {expr}) Number screen column of cursor or mark virtcol( {expr}) Number screen column of cursor or mark
visualmode( [expr]) String last visual mode used visualmode( [expr]) String last visual mode used
@ -5488,20 +5491,26 @@ sinh({expr}) *sinh()*
sort({list} [, {func} [, {dict}]]) *sort()* *E702* sort({list} [, {func} [, {dict}]]) *sort()* *E702*
Sort the items in {list} in-place. Returns {list}. If you Sort the items in {list} in-place. Returns {list}.
want a list to remain unmodified make a copy first: >
If you want a list to remain unmodified make a copy first: >
:let sortedlist = sort(copy(mylist)) :let sortedlist = sort(copy(mylist))
< Uses the string representation of each item to sort on. < Uses the string representation of each item to sort on.
Numbers sort after Strings, |Lists| after Numbers. Numbers sort after Strings, |Lists| after Numbers.
For sorting text in the current buffer use |:sort|. For sorting text in the current buffer use |:sort|.
When {func} is given and it is one then case is ignored. When {func} is given and it is one then case is ignored.
{dict} is for functions with the "dict" attribute. It will be
used to set the local variable "self". |Dictionary-function|
When {func} is a |Funcref| or a function name, this function When {func} is a |Funcref| or a function name, this function
is called to compare items. The function is invoked with two is called to compare items. The function is invoked with two
items as argument and must return zero if they are equal, 1 or items as argument and must return zero if they are equal, 1 or
bigger if the first one sorts after the second one, -1 or bigger if the first one sorts after the second one, -1 or
smaller if the first one sorts before the second one. smaller if the first one sorts before the second one.
{dict} is for functions with the "dict" attribute. It will be
used to set the local variable "self". |Dictionary-function|
Also see |uniq()|.
Example: > Example: >
func MyCompare(i1, i2) func MyCompare(i1, i2)
return a:i1 == a:i2 ? 0 : a:i1 > a:i2 ? 1 : -1 return a:i1 == a:i2 ? 0 : a:i1 > a:i2 ? 1 : -1
@ -6169,6 +6178,14 @@ undotree() *undotree()*
blocks. Each item may again have an "alt" blocks. Each item may again have an "alt"
item. item.
uniq({list} [, {func} [, {dict}]]) *uniq()* *E882*
Remove second and succeeding copies of repeated adjacent
{list} items in-place. Returns {list}. If you want a list
to remain unmodified make a copy first: >
:let newlist = uniq(copy(mylist))
< The default compare function uses the string representation of
each item. For the use of {func} and {dict} see |sort()|.
values({dict}) *values()* values({dict}) *values()*
Return a |List| with all the values of {dict}. The |List| is Return a |List| with all the values of {dict}. The |List| is
in arbitrary order. in arbitrary order.

View File

@ -942,6 +942,7 @@ New and extended functions: ~
|tagfiles()| List with tags file names |tagfiles()| List with tags file names
|taglist()| get list of matching tags (Yegappan Lakshmanan) |taglist()| get list of matching tags (Yegappan Lakshmanan)
|tr()| translate characters (Ron Aaron) |tr()| translate characters (Ron Aaron)
|uniq()| remove copies of repeated adjacent list items
|values()| get List of Dictionary values |values()| get List of Dictionary values
|winnr()| takes an argument: what window to use |winnr()| takes an argument: what window to use
|winrestview()| restore the view of the current window |winrestview()| restore the view of the current window

View File

@ -744,6 +744,7 @@ static void f_trunc __ARGS((typval_T *argvars, typval_T *rettv));
static void f_type __ARGS((typval_T *argvars, typval_T *rettv)); static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
static void f_undofile __ARGS((typval_T *argvars, typval_T *rettv)); static void f_undofile __ARGS((typval_T *argvars, typval_T *rettv));
static void f_undotree __ARGS((typval_T *argvars, typval_T *rettv)); static void f_undotree __ARGS((typval_T *argvars, typval_T *rettv));
static void f_uniq __ARGS((typval_T *argvars, typval_T *rettv));
static void f_values __ARGS((typval_T *argvars, typval_T *rettv)); static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv)); static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv)); static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
@ -8150,6 +8151,7 @@ static struct fst
{"type", 1, 1, f_type}, {"type", 1, 1, f_type},
{"undofile", 1, 1, f_undofile}, {"undofile", 1, 1, f_undofile},
{"undotree", 0, 0, f_undotree}, {"undotree", 0, 0, f_undotree},
{"uniq", 1, 3, f_uniq},
{"values", 1, 1, f_values}, {"values", 1, 1, f_values},
{"virtcol", 1, 1, f_virtcol}, {"virtcol", 1, 1, f_virtcol},
{"visualmode", 0, 1, f_visualmode}, {"visualmode", 0, 1, f_visualmode},
@ -17023,10 +17025,11 @@ static int item_compare_ic;
static char_u *item_compare_func; static char_u *item_compare_func;
static dict_T *item_compare_selfdict; static dict_T *item_compare_selfdict;
static int item_compare_func_err; static int item_compare_func_err;
static void do_sort_uniq __ARGS((typval_T *argvars, typval_T *rettv, int sort));
#define ITEM_COMPARE_FAIL 999 #define ITEM_COMPARE_FAIL 999
/* /*
* Compare functions for f_sort() below. * Compare functions for f_sort() and f_uniq() below.
*/ */
static int static int
#ifdef __BORLANDC__ #ifdef __BORLANDC__
@ -17100,9 +17103,10 @@ item_compare2(s1, s2)
* "sort({list})" function * "sort({list})" function
*/ */
static void static void
f_sort(argvars, rettv) do_sort_uniq(argvars, rettv, sort)
typval_T *argvars; typval_T *argvars;
typval_T *rettv; typval_T *rettv;
int sort;
{ {
list_T *l; list_T *l;
listitem_T *li; listitem_T *li;
@ -17111,12 +17115,12 @@ f_sort(argvars, rettv)
long i; long i;
if (argvars[0].v_type != VAR_LIST) if (argvars[0].v_type != VAR_LIST)
EMSG2(_(e_listarg), "sort()"); EMSG2(_(e_listarg), sort ? "sort()" : "uniq()");
else else
{ {
l = argvars[0].vval.v_list; l = argvars[0].vval.v_list;
if (l == NULL || tv_check_lock(l->lv_lock, if (l == NULL || tv_check_lock(l->lv_lock,
(char_u *)_("sort() argument"))) (char_u *)(sort ? _("sort() argument") : _("uniq() argument"))))
return; return;
rettv->vval.v_list = l; rettv->vval.v_list = l;
rettv->v_type = VAR_LIST; rettv->v_type = VAR_LIST;
@ -17163,29 +17167,72 @@ f_sort(argvars, rettv)
ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *))); ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
if (ptrs == NULL) if (ptrs == NULL)
return; return;
i = 0;
for (li = l->lv_first; li != NULL; li = li->li_next)
ptrs[i++] = li;
item_compare_func_err = FALSE; i = 0;
/* test the compare function */ if (sort)
if (item_compare_func != NULL {
&& item_compare2((void *)&ptrs[0], (void *)&ptrs[1]) /* sort(): ptrs will be the list to sort */
for (li = l->lv_first; li != NULL; li = li->li_next)
ptrs[i++] = li;
item_compare_func_err = FALSE;
/* test the compare function */
if (item_compare_func != NULL
&& item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
== ITEM_COMPARE_FAIL) == ITEM_COMPARE_FAIL)
EMSG(_("E702: Sort compare function failed")); EMSG(_("E702: Sort compare function failed"));
else
{
/* Sort the array with item pointers. */
qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
item_compare_func == NULL ? item_compare : item_compare2);
if (!item_compare_func_err)
{
/* Clear the List and append the items in sorted order. */
l->lv_first = l->lv_last = l->lv_idx_item = NULL;
l->lv_len = 0;
for (i = 0; i < len; ++i)
list_append(l, ptrs[i]);
}
}
}
else else
{ {
/* Sort the array with item pointers. */ int (*item_compare_func_ptr)__ARGS((const void *, const void *));
qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
item_compare_func == NULL ? item_compare : item_compare2); /* f_uniq(): ptrs will be a stack of items to remove */
item_compare_func_err = FALSE;
item_compare_func_ptr = item_compare_func
? item_compare2 : item_compare;
for (li = l->lv_first; li != NULL && li->li_next != NULL;
li = li->li_next)
{
if (item_compare_func_ptr((void *)&li, (void *)&li->li_next)
== 0)
ptrs[i++] = li;
if (item_compare_func_err)
{
EMSG(_("E882: Uniq compare function failed"));
break;
}
}
if (!item_compare_func_err) if (!item_compare_func_err)
{ {
/* Clear the List and append the items in the sorted order. */ while (--i >= 0)
l->lv_first = l->lv_last = l->lv_idx_item = NULL; {
l->lv_len = 0; li = ptrs[i]->li_next;
for (i = 0; i < len; ++i) ptrs[i]->li_next = li->li_next;
list_append(l, ptrs[i]); if (li->li_next != NULL)
li->li_next->li_prev = ptrs[i];
else
l->lv_last = ptrs[i];
list_fix_watch(l, li);
listitem_free(li);
l->lv_len--;
}
} }
} }
@ -17193,6 +17240,28 @@ f_sort(argvars, rettv)
} }
} }
/*
* "sort({list})" function
*/
static void
f_sort(argvars, rettv)
typval_T *argvars;
typval_T *rettv;
{
do_sort_uniq(argvars, rettv, TRUE);
}
/*
* "uniq({list})" function
*/
static void
f_uniq(argvars, rettv)
typval_T *argvars;
typval_T *rettv;
{
do_sort_uniq(argvars, rettv, FALSE);
}
/* /*
* "soundfold({word})" function * "soundfold({word})" function
*/ */

View File

@ -323,13 +323,15 @@ let l = [0, 1, 2, 3]
: $put ='caught ' . v:exception : $put ='caught ' . v:exception
:endtry :endtry
:" :"
:" reverse() and sort() :" reverse(), sort(), uniq()
:let l = ['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', [0, 1, 2], 'x8'] :let l = ['-0', 'A11', 2, 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5]
:$put =string(uniq(copy(l)))
:$put =string(reverse(l)) :$put =string(reverse(l))
:$put =string(reverse(reverse(l))) :$put =string(reverse(reverse(l)))
:$put =string(sort(l)) :$put =string(sort(l))
:$put =string(reverse(sort(l))) :$put =string(reverse(sort(l)))
:$put =string(sort(reverse(sort(l)))) :$put =string(sort(reverse(sort(l))))
:$put =string(uniq(sort(l)))
:" :"
:" splitting a string to a List :" splitting a string to a List
:$put =string(split(' aa bb ')) :$put =string(split(' aa bb '))

View File

@ -94,11 +94,13 @@ caught a:000[0]
caught a:000[2] caught a:000[2]
caught a:000[3] caught a:000[3]
[1, 2, [3, 9, 5, 6], {'a': 12, '5': 8}] [1, 2, [3, 9, 5, 6], {'a': 12, '5': 8}]
['x8', [0, 1, 2], 'foo6', 'foo', 4, 'xaaa', 2, 'A11', '-0'] ['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5]
['x8', [0, 1, 2], 'foo6', 'foo', 4, 'xaaa', 2, 'A11', '-0'] [1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0']
['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 2, 4, [0, 1, 2]] [1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0']
[[0, 1, 2], 4, 2, 'xaaa', 'x8', 'foo6', 'foo', 'A11', '-0'] ['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]]
['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 2, 4, [0, 1, 2]] [[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0']
['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]]
['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]]
['aa', 'bb'] ['aa', 'bb']
['aa', 'bb'] ['aa', 'bb']
['', 'aa', 'bb', ''] ['', 'aa', 'bb', '']

View File

@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
218,
/**/ /**/
217, 217,
/**/ /**/