Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort an array of object literals #21

Open
travispaul opened this issue Feb 26, 2014 · 12 comments
Open

Sort an array of object literals #21

travispaul opened this issue Feb 26, 2014 · 12 comments

Comments

@travispaul
Copy link
Contributor

In my application I have the need to sort an array of object literals by a key, and the key can be any type. For example:

this...

{
  "myArray": [
    {"key": "B", "value": "Buzz"},
    {"key": true, "value": "Baz"},
    {"key": "42", "value": "Flam"},
    {"key": 1, "value": "Bar"},
    {"key": "A", "value": "Foo"},
    {"key": false, "value": "Flub"},
    {"key": 2, "value": "Fizz"},
  ]
}

should sort to to perhaps something like this...

{
  "myArray": [
    {"key": true, "value": "Baz"},
    {"key": false, "value": "Flub"},
    {"key": 1, "value": "Bar"},
    {"key": 2, "value": "Fizz"},
    {"key": "42", "value": "Flam"},
    {"key": "A", "value": "Foo"},
    {"key": "B", "value": "Buzz"},
  ]
}

I am not aware of any way to do this within the library itself but I can think of how to do it outside the library (looping over the array, sorting the keys and attaching the literals into a new array). I am curious if this use case is common enough that it would make sense being in the library itself, or if there was some clever way to use selectors?

@minego
Copy link
Member

minego commented Feb 26, 2014

On 02/26/2014 02:52 PM, Travis Paul wrote:

In my application I have the need to sort an array of object literals by
a key, and the key can be any type. For example:

this...

{
"myArray": [
{"key": "B", "value": "Buzz"},
{"key": true, "value": "Baz"},
{"key": "42", "value": "Flam"},
{"key": 1, "value": "Bar"},
{"key": "A", "value": "Foo"},
{"key": false, "value": "Flub"},
{"key": 2, "value": "Fizz"},
]
}

should sort to to perhaps something like this...

{
"myArray": [
{"key": true, "value": "Baz"},
{"key": false, "value": "Flub"},
{"key": 1, "value": "Bar"},
{"key": 2, "value": "Fizz"},
{"key": "42", "value": "Flam"},
{"key": "A", "value": "Foo"},
{"key": "B", "value": "Buzz"},
]
}

I am not aware of any way to do this within the library itself but I can
think of how to do it outside the library (looping over the array,
sorting the keys and attaching the literals into a new array). I am
curious if this use case is common enough that it would make sense being
in the library itself, or if there was some clever way to use selectors?


Reply to this email directly or view it on GitHub
#21.

There is not a way to do this in the library currently, but I like the
idea. Do you have any suggestions for what you'd like the API to look like?

Micah

@penduin
Copy link
Member

penduin commented Feb 26, 2014

We could do something like: WJESortArray(doc, compareCB)
with behavior and callback conventions imitating JavaScript's Array.prototype.sort:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

It might be useful to sort objects as well as arrays, though I'm not sure if that could/should use the same mechanism or have its own WJESortObject callback would just take the key names instead of an arbitrary WJElement.

Somehow being able to use dirent's alphasort() would also be a neat trick, but I can't think of a way to do that (for arbitrary array sorting anyway) without limiting flexibility pretty severely.

@travispaul
Copy link
Contributor Author

Below is what initially came to mind:

void WJEArraySortByKey(WJElement array, char *key, WJEAction order);
// {"myArray":[{"key":"A"},{"key":"B"},{"key":"C"}]}
WJEArraySortKey(WJEGet(doc, "myArray"), "key", WJE_ASCENDING);

And maybe an accompanying flat array sort?

void WJEArraySort(WJElement array, WJEAction order);
// {"myArray":["C", "B", "A"]}
WJEArraySort(WJEGet(doc, "myArray"), WJE_DESCENDING)

But that's just me thinking out loud. I like the idea of imitating JavaScript's Array.prototype.sort.

@minego
Copy link
Member

minego commented Feb 26, 2014

On 02/26/2014 03:15 PM, penduin wrote:

We could do something like: WJESortArray(doc, compareCB)
with behavior and callback conventions imitating JavaScript's
Array.prototype.sort:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

It might be useful to sort objects as well as arrays, though I'm not
sure if that could/should use the same mechanism or have its own
WJESortObject callback would just take the key names instead of an
arbitrary WJElement.

Somehow being able to use dirent's alphasort() would also be a neat
trick, but I can't think of a way to do that (for arbitrary array
sorting anyway) without limiting flexibility pretty severely.


Reply to this email directly or view it on GitHub
#21 (comment).

I like this approach.

The same function would work just fine for arrays and objects.

typedef int (WJESortCB *)(WJElement a, WJElement b, void *data);
WJESort(WJElement o, WJESortCB cb, void *data);

If the object is an array then a->name and b->name will be NULL. If it
is an object then they will be non-null. If WJESort() is called on any
object other than an array or an object then it will simply be a no-op.

@penduin
Copy link
Member

penduin commented Feb 26, 2014

Yeah, I like that. (Also duh, not sure why I got caught up on a separate one for objects :^) Including a couple of helpers for alphabetical sorting of strings/keys might be handy. Such a thing could even be the default, if NULL is passed for the callback. (Again emulating JS's array sort)

@minego
Copy link
Member

minego commented Feb 26, 2014

On 02/26/2014 03:59 PM, penduin wrote:

Yeah, I like that. (Also duh, not sure why I got caught up on a separate
one for objects :^) Including a couple of helpers for alphabetical
sorting of strings/keys might be handy. Such a thing could even be the
default, if NULL is passed for the callback. (Again emulating JS's array
sort)


Reply to this email directly or view it on GitHub
#21 (comment).

Sounds good. Do you feel like writing it? :)

@travispaul
Copy link
Contributor Author

If both of you are busy with other things I would be willing to create a branch and attempt to implement it. However, I am a C novice so you will probably need to yell at me until it looks good enough to merge in. It would take me longer to implement it than either of you, but it would be a great learning experience for me and I need the feature within the next couple of months anyways.

@minego
Copy link
Member

minego commented Feb 27, 2014

On 02/27/2014 09:57 AM, Travis Paul wrote:

If both of you are busy with other things I would be willing to create a
branch and attempt to implement it. However, I am a C novice so you will
probably need to yell at me until it looks good enough to merge in. It
would take me longer to implement it than either of you, but it would be
a great learning experience for me and I need the feature within the
next couple of months anyways.


Reply to this email directly or view it on GitHub
#21 (comment).

I would love that. I'm very happy to help with any questions about C you
may have.

@travispaul
Copy link
Contributor Author

Thanks @minego, I really appreciate it! I will most likely break ground next weekend (March 8th) as I have some other things to finish up this weekend.

@primohan01
Copy link

Hi All,
I just want to read the array elements in c language. Could you share the example of the same.

{
"Array": [1,2,3]

}

I tried through WJArray but it is returning junk values.

@minego
Copy link
Member

minego commented Oct 1, 2014

On 10/01/14 01:08, primohan01 wrote:

Hi All,
I just want to read the array elements in c language. Could you share
the example of the same.

{
"Array": [1,2,3]

}

I tried through WJArray but it is returning junk values.


Reply to this email directly or view it on GitHub
#21 (comment).

Hi,

You need to use the correct function to get the values as the C type
that you want. So, in this case you would probably want to do something
like this:

WJElement last;
int v;

l = NULL;
while (-1 != (v = _WJENumber(doc, "[]", &last, WJE_GET, -1))) {
printf("Read a value: %d\n", v);
}

The WJENumber() function will find the first element that matches the
selector (in this case "[]" which will match any child of the outer
array) attempt to convert the value to a number and return it.

The _ version is used for finding multiple matches and takes an extra
argument (last) to keep track of the last match.

The final argument is the value to return if there is no match.

I hope this helps. Please don't hesitate to ask if you have any other
questions.

Micah

@primohan01
Copy link

Dear Micah,
Could you please also suggest the Wjelement API to compare the two json object. As I need to compare the two json objects for similar values.apart form this, I believe unique property value validation in json object is not possible and there is no API available for the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants