Function sortuniq() for sort and remove duplicates.

--
--
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    Tue Mar 18 23:37:37 2014 -0400
@@ -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      Tue Mar 18 23:37:37 2014 -0400
@@ -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    Tue Mar 18 23:37:37 2014 -0400
@@ -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  Tue Mar 18 23:37:37 2014 -0400
@@ -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        Tue Mar 18 23:37:37 2014 -0400
@@ -93,6 +93,14 @@
     char_u     *ll_newkey;     /* New key for Dict in alloc. mem or NULL. */
 } lval_T;
 
+/*
+ * Structure used by f_sortuniq().
+ */
+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__
@@ -17105,6 +17120,32 @@
     return res;
 }
 
+    static int
+#ifdef __BORLANDC__
+_RTLENTRYF
+#endif
+item_compare_uniq(s1, s2)
+    const void *s1;
+    const void *s2;
+{
+    ulistitem_T        *p1, *p2;
+    int                res;
+
+    p1 = (ulistitem_T *)s1;
+    p2 = (ulistitem_T *)s2;
+
+    if (item_compare_func)
+       res = item_compare2((void *)p1, (void *)p2);
+    else
+       res = item_compare((void *)p1, (void *)p2);
+
+    if ( res == 0 )
+    {
+       p2->is_duplicate = TRUE;
+    }
+    return res;
+}
+
 /*
  * "sort({list})" function
  */
@@ -17203,6 +17244,120 @@
 }
 
 /*
+ * "sortuniq({list})" function
+ */
+    static void
+f_sortuniq(argvars, rettv)
+    typval_T   *argvars;
+    typval_T   *rettv;
+{
+    list_T     *l;
+    listitem_T *li;
+    ulistitem_T        *ptrs;
+    ulistitem_T        *p;
+    long       len;
+    long       i;
+
+    if (argvars[0].v_type != VAR_LIST)
+       EMSG2(_(e_listarg), "sortuniq()");
+    else
+    {
+       l = argvars[0].vval.v_list;
+       if (l == NULL || tv_check_lock(l->lv_lock,
+                                            (char_u *)_("sortuniq() 
argument")))
+           return;
+       rettv->vval.v_list = l;
+       rettv->v_type = VAR_LIST;
+       ++l->lv_refcount;
+
+       len = list_len(l);
+       if (len <= 1)
+           return;     /* short list sorts pretty quickly */
+
+       item_compare_ic = FALSE;
+       item_compare_func = NULL;
+       item_compare_selfdict = NULL;
+       if (argvars[1].v_type != VAR_UNKNOWN)
+       {
+           /* optional second argument: {func} */
+           if (argvars[1].v_type == VAR_FUNC)
+               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 */
+               if (i == 1)
+                   item_compare_ic = TRUE;
+               else
+                   item_compare_func = get_tv_string(&argvars[1]);
+           }
+
+           if (argvars[2].v_type != VAR_UNKNOWN)
+           {
+               /* optional third argument: {dict} */
+               if (argvars[2].v_type != VAR_DICT)
+               {
+                   EMSG(_(e_dictreq));
+                   return;
+               }
+               item_compare_selfdict = argvars[2].vval.v_dict;
+           }
+       }
+
+       /* Make an array with each entry pointing to an item in the List. */
+       ptrs = (ulistitem_T *)alloc((int)(len * sizeof(*ptrs)));
+       if (ptrs == NULL)
+           return;
+       p = ptrs;
+       for (li = l->lv_first; li != NULL; li = li->li_next)
+       {
+           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].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(*ptrs),
+                   item_compare_uniq);
+
+           if (!item_compare_func_err)
+           {
+               /* Clear the List and append the items in the sorted order.
+                * Duplicates are removed. */
+               l->lv_first = l->lv_last = l->lv_idx_item = NULL;
+               l->lv_len = 0;
+               p = ptrs;
+               for (i = 0; i < len; ++i, ++p)
+               {
+                   if (p->is_duplicate)
+                   {
+                       list_fix_watch( l, p->ll_li );
+                       listitem_free( p->ll_li );
+                   }
+                   else
+                   {
+                       list_append(l, p->ll_li);
+                   }
+               }
+           }
+       }
+
+       vim_free(ptrs);
+    }
+}
+
+/*
  * "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     Tue Mar 18 23:37:37 2014 -0400
@@ -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     Tue Mar 18 23:37:37 2014 -0400
@@ -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', '']

Raspunde prin e-mail lui