> 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 vim_dev+unsubscr...@googlegroups.com. 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', '']