]> granicus.if.org Git - jq/commitdiff
to_entries should not sort keys (fix #561)
authorNicolas Williams <nico@cryptonector.com>
Wed, 1 Oct 2014 02:49:37 +0000 (21:49 -0500)
committerNicolas Williams <nico@cryptonector.com>
Wed, 1 Oct 2014 02:52:30 +0000 (21:52 -0500)
builtin.c
docs/content/3.manual/manual.yml
jv.h
jv_aux.c

index 2426f6c997192011c7a870ba5585fe035c6ce7d1..65b6de6a2bdbbcddb5334988161b0b67c5e12808 100644 (file)
--- a/builtin.c
+++ b/builtin.c
@@ -488,6 +488,14 @@ static jv f_keys(jq_state *jq, jv input) {
   }
 }
 
+static jv f_keys_unsorted(jq_state *jq, jv input) {
+  if (jv_get_kind(input) == JV_KIND_OBJECT || jv_get_kind(input) == JV_KIND_ARRAY) {
+    return jv_keys_unsorted(input);
+  } else {
+    return type_error(input, "has no keys");
+  }
+}
+
 static jv f_sort(jq_state *jq, jv input){
   if (jv_get_kind(input) == JV_KIND_ARRAY) {
     return jv_sort(input, jv_copy(input));
@@ -860,6 +868,7 @@ static const struct cfunction function_list[] = {
   {(cfunction_ptr)f_tonumber, "tonumber", 1},
   {(cfunction_ptr)f_tostring, "tostring", 1},
   {(cfunction_ptr)f_keys, "keys", 1},
+  {(cfunction_ptr)f_keys_unsorted, "keys_unsorted", 1},
   {(cfunction_ptr)f_startswith, "startswith", 2},
   {(cfunction_ptr)f_endswith, "endswith", 2},
   {(cfunction_ptr)f_ltrimstr, "ltrimstr", 2},
@@ -965,7 +974,7 @@ static const char* const jq_builtins[] = {
   "def recurse: recurse(.[]?);",
   "def recurse_down: recurse;",
 
-  "def to_entries: [keys[] as $k | {key: $k, value: .[$k]}];",
+  "def to_entries: [keys_unsorted[] as $k | {key: $k, value: .[$k]}];",
   "def from_entries: map({(.key): .value}) | add | .//={};",
   "def with_entries(f): to_entries | map(f) | from_entries;",
   "def reverse: [.[length - 1 - range(0;length)]];",
index 4e510f8d0b6b1f25f1b29ada9917f331c0f27de4..d1996920693f4fe8b5bb0ba16bde9bab1ccb9565 100644 (file)
@@ -588,7 +588,7 @@ sections:
             input: '[[1,2], "string", {"a":2}, null]'
             output: [2, 6, 1, 0]
 
-      - title: "`keys`"
+      - title: "`keys`, `keys_unsorted`"
         body: |
 
           The builtin function `keys`, when given an object, returns
@@ -603,6 +603,10 @@ sections:
           When `keys` is given an array, it returns the valid indices
           for that array: the integers from 0 to length-1.
 
+          The `keys_unsorted` function is just like `keys`, but if
+          the input is an object then the keys will not be sorted,
+          instead the keys will roughly be in insertion order.
+
         examples:
           - program: 'keys'
             input: '{"abc": 1, "abcd": 2, "Foo": 3}'
diff --git a/jv.h b/jv.h
index 29738eda005e22950902623dcd86455b790d9b97..465070ad0c71b4105181a7bcb3b68b61adf37d1d 100644 (file)
--- a/jv.h
+++ b/jv.h
@@ -177,6 +177,7 @@ jv jv_setpath(jv, jv, jv);
 jv jv_getpath(jv, jv);
 jv jv_delpaths(jv, jv);
 jv jv_keys(jv /*object or array*/);
+jv jv_keys_unsorted(jv /*object or array*/);
 int jv_cmp(jv, jv);
 jv jv_group(jv, jv);
 jv jv_sort(jv, jv);
index dec5ce20d01d5ea16c90a24acb2cbd4462baa2ea..d859dc4912498f0ca64a7c6eb60db5f758d4d9ff 100644 (file)
--- a/jv_aux.c
+++ b/jv_aux.c
@@ -428,6 +428,18 @@ static int string_cmp(const void* pa, const void* pb){
   return r;
 }
 
+jv jv_keys_unsorted(jv x) {
+  if (jv_get_kind(x) != JV_KIND_OBJECT)
+    return jv_keys(x);
+  jv answer = jv_array_sized(jv_object_length(jv_copy(x)));
+  jv_object_foreach(x, key, value) {
+    answer = jv_array_append(answer, key);
+    jv_free(value);
+  }
+  jv_free(x);
+  return answer;
+}
+
 jv jv_keys(jv x) {
   if (jv_get_kind(x) == JV_KIND_OBJECT) {
     int nkeys = jv_object_length(jv_copy(x));