Skip to content

Commit b00da1d

Browse files
committed
patch 7.4.951
Problem: Sorting number strings does not work as expected. (Luc Hermitte) Solution: Add the 'N" argument to sort()
1 parent 4649ded commit b00da1d

6 files changed

Lines changed: 52 additions & 1 deletion

File tree

runtime/doc/eval.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5803,6 +5803,10 @@ sort({list} [, {func} [, {dict}]]) *sort()* *E702*
58035803
strtod() function to parse numbers, Strings, Lists, Dicts and
58045804
Funcrefs will be considered as being 0).
58055805

5806+
When {func} is given and it is 'N' then all items will be
5807+
sorted numerical. This is like 'n' but a string containing
5808+
digits will be used as the number they represent.
5809+
58065810
When {func} is a |Funcref| or a function name, this function
58075811
is called to compare items. The function is invoked with two
58085812
items as argument and must return zero if they are equal, 1 or
@@ -5817,6 +5821,11 @@ sort({list} [, {func} [, {dict}]]) *sort()* *E702*
58175821
on numbers, text strings will sort next to each other, in the
58185822
same order as they were originally.
58195823

5824+
The sort is stable, items which compare equal (as number or as
5825+
string) will keep their relative position. E.g., when sorting
5826+
on numbers, text strings will sort next to each other, in the
5827+
same order as they were originally.
5828+
58205829
Also see |uniq()|.
58215830

58225831
Example: >

src/eval.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17928,6 +17928,7 @@ typedef struct
1792817928

1792917929
static int item_compare_ic;
1793017930
static int item_compare_numeric;
17931+
static int item_compare_numbers;
1793117932
static char_u *item_compare_func;
1793217933
static dict_T *item_compare_selfdict;
1793317934
static int item_compare_func_err;
@@ -17958,6 +17959,15 @@ item_compare(s1, s2)
1795817959
si2 = (sortItem_T *)s2;
1795917960
tv1 = &si1->item->li_tv;
1796017961
tv2 = &si2->item->li_tv;
17962+
17963+
if (item_compare_numbers)
17964+
{
17965+
long v1 = get_tv_number(tv1);
17966+
long v2 = get_tv_number(tv2);
17967+
17968+
return v1 == v2 ? 0 : v1 > v2 ? 1 : -1;
17969+
}
17970+
1796117971
/* tv2string() puts quotes around a string and allocates memory. Don't do
1796217972
* that for string variables. Use a single quote when comparing with a
1796317973
* non-string to do what the docs promise. */
@@ -18091,6 +18101,7 @@ do_sort_uniq(argvars, rettv, sort)
1809118101

1809218102
item_compare_ic = FALSE;
1809318103
item_compare_numeric = FALSE;
18104+
item_compare_numbers = FALSE;
1809418105
item_compare_func = NULL;
1809518106
item_compare_selfdict = NULL;
1809618107
if (argvars[1].v_type != VAR_UNKNOWN)
@@ -18116,6 +18127,11 @@ do_sort_uniq(argvars, rettv, sort)
1811618127
item_compare_func = NULL;
1811718128
item_compare_numeric = TRUE;
1811818129
}
18130+
else if (STRCMP(item_compare_func, "N") == 0)
18131+
{
18132+
item_compare_func = NULL;
18133+
item_compare_numbers = TRUE;
18134+
}
1811918135
else if (STRCMP(item_compare_func, "i") == 0)
1812018136
{
1812118137
item_compare_func = NULL;

src/testdir/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \
6969
test_writefile.out
7070

7171
NEW_TESTS = test_assert.res \
72-
test_undolevels.res
72+
test_alot.res
7373

7474
SCRIPTS_GUI = test16.out
7575

src/testdir/test_alot.vim

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
" A series of tests that can run in one Vim invocation.
2+
" This makes testing go faster, since Vim doesn't need to restart.
3+
4+
source test_undolevels.vim
5+
source test_sort.vim

src/testdir/test_sort.vim

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
" Test sort()
2+
3+
func Test_sort_strings()
4+
" numbers compared as strings
5+
call assert_equal([1, 2, 3], sort([3, 2, 1]))
6+
call assert_equal([13, 28, 3], sort([3, 28, 13]))
7+
endfunc
8+
9+
func Test_sort_numeric()
10+
call assert_equal([1, 2, 3], sort([3, 2, 1], 'n'))
11+
call assert_equal([3, 13, 28], sort([13, 28, 3], 'n'))
12+
" strings are not sorted
13+
call assert_equal(['13', '28', '3'], sort(['13', '28', '3'], 'n'))
14+
endfunc
15+
16+
func Test_sort_numbers()
17+
call assert_equal([3, 13, 28], sort([13, 28, 3], 'N'))
18+
call assert_equal(['3', '13', '28'], sort(['13', '28', '3'], 'N'))
19+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,8 @@ static char *(features[]) =
741741

742742
static int included_patches[] =
743743
{ /* Add new patch number below this line */
744+
/**/
745+
951,
744746
/**/
745747
950,
746748
/**/

0 commit comments

Comments
 (0)