> Looks like you made a copy of f_sort() and modified it a bit. That's a
>
> lot of duplicate code. Better move the common stuff into a function
>
> that's used by both sort() and sortuniq().
Fixed
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff -r 5c956eeefc1b runtime/doc/change.txt
--- a/runtime/doc/change.txt Tue Mar 18 23:36:13 2014 -0400
+++ b/runtime/doc/change.txt Thu Mar 20 12:04:35 2014 +0700
@@ -1650,7 +1650,7 @@
7. Sorting text *sorting*
Vim has a sorting function and a sorting command. The sorting function can be
-found here: |sort()|.
+found here: |sort()|, |sortuniq()|.
*:sor* *:sort*
:[range]sor[t][!] [i][u][r][n][x][o] [/{pattern}/]
diff -r 5c956eeefc1b runtime/doc/eval.txt
--- a/runtime/doc/eval.txt Tue Mar 18 23:36:13 2014 -0400
+++ b/runtime/doc/eval.txt Thu Mar 20 12:04:35 2014 +0700
@@ -326,6 +326,7 @@
Changing the order of items in a list: >
:call sort(list) " sort a list alphabetically
+ :call sortuniq(list) " sort a list and remove duplicates
:call reverse(list) " reverse the order of items
@@ -1956,6 +1957,8 @@
sinh( {expr}) Float hyperbolic sine of {expr}
sort( {list} [, {func} [, {dict}]])
List sort {list}, using {func} to compare
+sortuniq( {list} [, {func} [, {dict}]])
+ List sort {list} and remove duplicates
soundfold( {word}) String sound-fold {word}
spellbadword() String badly spelled word at cursor
spellsuggest( {word} [, {max} [, {capital}]])
@@ -5513,6 +5516,11 @@
return a:i1 - a:i2
endfunc
<
+
+sortuniq({list} [, {func} [, {dict}]]) *sortuniq()* *E702*
+ Sort the items in {list} as like |sort()| does and
+ remove duplicates.
+
*soundfold()*
soundfold({word})
Return the sound-folded equivalent of {word}. Uses the first
diff -r 5c956eeefc1b runtime/doc/usr_41.txt
--- a/runtime/doc/usr_41.txt Tue Mar 18 23:36:13 2014 -0400
+++ b/runtime/doc/usr_41.txt Thu Mar 20 12:04:35 2014 +0700
@@ -622,6 +622,7 @@
filter() remove selected items from a List
map() change each List item
sort() sort a List
+ sortuniq() sort a List and remove duplicate values
reverse() reverse the order of a List
split() split a String into a List
join() join List items into a String
diff -r 5c956eeefc1b runtime/doc/version7.txt
--- a/runtime/doc/version7.txt Tue Mar 18 23:36:13 2014 -0400
+++ b/runtime/doc/version7.txt Thu Mar 20 12:04:35 2014 +0700
@@ -927,6 +927,7 @@
|setqflist()| modify a quickfix list (Yegappan Lakshmanan)
|settabwinvar()| set variable in window of specified tab page
|sort()| sort a List
+|sortuniq()| sort a List and remove duplicates
|soundfold()| get the sound-a-like equivalent of a word
|spellbadword()| get a badly spelled word
|spellsuggest()| get suggestions for correct spelling
diff -r 5c956eeefc1b src/eval.c
--- a/src/eval.c Tue Mar 18 23:36:13 2014 -0400
+++ b/src/eval.c Thu Mar 20 12:04:35 2014 +0700
@@ -93,6 +93,14 @@
char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */
} lval_T;
+/*
+ * Structure used by sort_internal().
+ */
+typedef struct ulistitem_T
+{
+ listitem_T *ll_li; /* list item */
+ int is_duplicate; /* TRUE, if item already in list */
+} ulistitem_T;
static char *e_letunexp = N_("E18: Unexpected characters in :let");
static char *e_listidx = N_("E684: list index out of range: %ld");
@@ -695,6 +703,7 @@
static void f_sinh __ARGS((typval_T *argvars, typval_T *rettv));
#endif
static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_sortuniq __ARGS((typval_T *argvars, typval_T *rettv));
static void f_soundfold __ARGS((typval_T *argvars, typval_T *rettv));
static void f_spellbadword __ARGS((typval_T *argvars, typval_T *rettv));
static void f_spellsuggest __ARGS((typval_T *argvars, typval_T *rettv));
@@ -8101,6 +8110,7 @@
{"sinh", 1, 1, f_sinh},
#endif
{"sort", 1, 3, f_sort},
+ {"sortuniq", 1, 3, f_sortuniq},
{"soundfold", 1, 1, f_soundfold},
{"spellbadword", 0, 1, f_spellbadword},
{"spellsuggest", 1, 3, f_spellsuggest},
@@ -17027,6 +17037,11 @@
_RTLENTRYF
#endif
item_compare2 __ARGS((const void *s1, const void *s2));
+static int
+#ifdef __BORLANDC__
+ _RTLENTRYF
+#endif
+ item_compare_uniq __ARGS((const void *s1, const void *s2));
static int item_compare_ic;
static char_u *item_compare_func;
@@ -17035,7 +17050,7 @@
#define ITEM_COMPARE_FAIL 999
/*
- * Compare functions for f_sort() below.
+ * Compare functions for f_sort() and f_sortuniq() below.
*/
static int
#ifdef __BORLANDC__
@@ -17045,14 +17060,18 @@
const void *s1;
const void *s2;
{
+ ulistitem_T *uli1, *uli2;
char_u *p1, *p2;
char_u *tofree1, *tofree2;
int res;
char_u numbuf1[NUMBUFLEN];
char_u numbuf2[NUMBUFLEN];
- p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1, 0);
- p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2, 0);
+ uli1 = (ulistitem_T *)s1;
+ uli2 = (ulistitem_T *)s2;
+
+ p1 = tv2string(&uli1->ll_li->li_tv, &tofree1, numbuf1, 0);
+ p2 = tv2string(&uli2->ll_li->li_tv, &tofree2, numbuf2, 0);
if (p1 == NULL)
p1 = (char_u *)"";
if (p2 == NULL)
@@ -17074,19 +17093,23 @@
const void *s1;
const void *s2;
{
+ ulistitem_T *uli1, *uli2;
int res;
typval_T rettv;
typval_T argv[3];
int dummy;
+ uli1 = (ulistitem_T *)s1;
+ uli2 = (ulistitem_T *)s2;
+
/* shortcut after failure in previous call; compare all items equal */
if (item_compare_func_err)
return 0;
/* copy the values. This is needed to be able to set v_lock to VAR_FIXED
* in the copy without changing the original list items. */
- copy_tv(&(*(listitem_T **)s1)->li_tv, &argv[0]);
- copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
+ copy_tv(&uli1->ll_li->li_tv, &argv[0]);
+ copy_tv(&uli2->ll_li->li_tv, &argv[1]);
rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
res = call_func(item_compare_func, (int)STRLEN(item_compare_func),
@@ -17105,27 +17128,54 @@
return res;
}
-/*
- * "sort({list})" function
- */
- static void
-f_sort(argvars, rettv)
- typval_T *argvars;
- typval_T *rettv;
+ static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+item_compare_uniq(s1, s2)
+ const void *s1;
+ const void *s2;
+{
+ ulistitem_T *uli2;
+ int res;
+
+ uli2 = (ulistitem_T *)s2;
+
+ if (item_compare_func)
+ res = item_compare2((void *)s1, (void *)s2);
+ else
+ res = item_compare((void *)s1, (void *)s2);
+
+ if ( res == 0 )
+ {
+ uli2->is_duplicate = TRUE;
+ }
+ return res;
+}
+
+ static void
+sort_internal(argvars, rettv, uniq)
+ typval_T *argvars;
+ typval_T *rettv;
+ int uniq;
{
list_T *l;
listitem_T *li;
- listitem_T **ptrs;
+ ulistitem_T *ptrs;
+ ulistitem_T *p;
long len;
long i;
+ int error = FALSE;
if (argvars[0].v_type != VAR_LIST)
- EMSG2(_(e_listarg), "sort()");
+ EMSG2(_(e_listarg), uniq ? "sortuniq()" : "sort()");
else
{
l = argvars[0].vval.v_list;
- if (l == NULL || tv_check_lock(l->lv_lock,
- (char_u *)_("sort() argument")))
+ i = tv_check_lock(l->lv_lock,
+ (char_u *)_( uniq ? "sortuniq() argument" :
+ "sort() argument"));
+ if (l == NULL || i)
return;
rettv->vval.v_list = l;
rettv->v_type = VAR_LIST;
@@ -17145,8 +17195,6 @@
item_compare_func = argvars[1].vval.v_string;
else
{
- int error = FALSE;
-
i = get_tv_number_chk(&argvars[1], &error);
if (error)
return; /* type error; errmsg already given */
@@ -17169,32 +17217,48 @@
}
/* Make an array with each entry pointing to an item in the List. */
- ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
+ ptrs = (ulistitem_T *)alloc((int)(len * sizeof(*ptrs)));
if (ptrs == NULL)
return;
- i = 0;
+ p = ptrs;
for (li = l->lv_first; li != NULL; li = li->li_next)
- ptrs[i++] = li;
+ {
+ p->ll_li = li;
+ p->is_duplicate = FALSE;
+ p++;
+ }
item_compare_func_err = FALSE;
/* test the compare function */
if (item_compare_func != NULL
- && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
+ && item_compare2((void *)&ptrs[0].ll_li, (void *)&ptrs[1].ll_li)
== ITEM_COMPARE_FAIL)
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);
+ qsort((void *)ptrs, (size_t)len, sizeof(*ptrs),
+ uniq ? item_compare_uniq : item_compare_func ?
item_compare2 : item_compare);
if (!item_compare_func_err)
{
- /* Clear the List and append the items in the sorted order. */
+ /* Clear the List and append the items in the sorted order.
+ * If needed, remove duplicates. */
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]);
+ p = ptrs;
+ for (i = 0; i < len; ++i, ++p)
+ {
+ if (uniq && p->is_duplicate)
+ {
+ list_fix_watch( l, p->ll_li );
+ listitem_free( p->ll_li );
+ }
+ else
+ {
+ list_append(l, p->ll_li);
+ }
+ }
}
}
@@ -17203,6 +17267,28 @@
}
/*
+ * "sort({list})" function
+ */
+ static void
+f_sort(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ return sort_internal(argvars, rettv, FALSE);
+}
+
+/*
+ * "sortuniq({list})" function
+ */
+ static void
+f_sortuniq(argvars, rettv)
+ typval_T *argvars;
+ typval_T *rettv;
+{
+ return sort_internal(argvars, rettv, TRUE);
+}
+
+/*
* "soundfold({word})" function
*/
static void
diff -r 5c956eeefc1b src/testdir/test55.in
--- a/src/testdir/test55.in Tue Mar 18 23:36:13 2014 -0400
+++ b/src/testdir/test55.in Thu Mar 20 12:04:35 2014 +0700
@@ -323,13 +323,16 @@
: $put ='caught ' . v:exception
:endtry
:"
-:" reverse() and sort()
-:let l = ['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', [0, 1, 2], 'x8']
+:" reverse(), sort(), sortuniq()
+:let l = ['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', [0, 1, 2], 'x8', [0, 1,
2], 2, 'foo', 1.5]
:$put =string(reverse(l))
:$put =string(reverse(reverse(l)))
:$put =string(sort(l))
:$put =string(reverse(sort(l)))
:$put =string(sort(reverse(sort(l))))
+:$put =string(sortuniq(l))
+:$put =string(reverse(sortuniq(l)))
+:$put =string(sortuniq(reverse(sortuniq(l))))
:"
:" splitting a string to a List
:$put =string(split(' aa bb '))
diff -r 5c956eeefc1b src/testdir/test55.ok
--- a/src/testdir/test55.ok Tue Mar 18 23:36:13 2014 -0400
+++ b/src/testdir/test55.ok Thu Mar 20 12:04:35 2014 +0700
@@ -94,11 +94,14 @@
caught a:000[2]
caught a:000[3]
[1, 2, [3, 9, 5, 6], {'a': 12, '5': 8}]
-['x8', [0, 1, 2], 'foo6', 'foo', 4, 'xaaa', 2, 'A11', '-0']
-['x8', [0, 1, 2], 'foo6', 'foo', 4, 'xaaa', 2, 'A11', '-0']
-['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 2, 4, [0, 1, 2]]
-[[0, 1, 2], 4, 2, 'xaaa', 'x8', 'foo6', 'foo', 'A11', '-0']
-['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 2, 4, [0, 1, 2]]
+[1.5, 'foo', 2, [0, 1, 2], 'x8', [0, 1, 2], 'foo6', 'foo', 4, 'xaaa', 2,
'A11', '-0']
+[1.5, 'foo', 2, [0, 1, 2], 'x8', [0, 1, 2], 'foo6', 'foo', 4, 'xaaa', 2,
'A11', '-0']
+['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [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]]
+[[0, 1, 2], 4, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'A11', '-0']
+['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]]
['aa', 'bb']
['aa', 'bb']
['', 'aa', 'bb', '']