Incrementing integers - ceylon

I'm having some trouble incrementing a variable integer. This code:
variable Integer myInteger = -1;
Integer getInteger () {
myInteger = myInteger + 1;
print("myInteger: " + myInteger.string);
return Integer(myInteger);
}
Array<Integer> integers =
Array.ofSize(
4,
getInteger());
print(integers);
Gives this output:
myInteger: 0
{ 0, 0, 0, 0 }
while the intended output was:
myInteger: 0
myInteger: 1
myInteger: 2
myInteger: 3
{ 0, 1, 2, 3 }
What's up with that?

Your example, which I assume is contrived, can be written as Array(0:4) or Array(0..3). But assuming that you have some good reason to want to loop over a generating function, here is how I would write it:
Array(loop(0)((i) => i+1).take(4))
Or, equivalently:
Array(loop(0)(Integer.successor).take(4))
Or even:
Array(loop(0)(1.plus).take(4))
That's much better, IMO, than using a stream which accesses a variable in an outer scope.

You already found what is happening here ... the constructor Array.ofSize(n, val) is creating an array filled with n times the same value.
A way of doing what you want might be this:
Array<Integer> integers =
Array({ getInteger() }.repeat(4));
(Try it.)
The expression in the iterable enumeration (this is the { getInteger() } here) is evaluated lazily each time the iterator's next method is invoked (which is happening 4 times here, due to repeating the iterable 4 times).
Note that it won't work if you use a sequence enumeration [ ... ] instead, those are non-lazy.

Related

How to conditionally return specific value with another in JSONPath?

I've got an object like this one:
{
"content": {
"iteration_size": 1
}
}
I need a JSONPath which returns null if the value of next_item is exactly 1, or the value of iteration_size otherwise. So the above should return null and "iteration_size": 2 should return 2. Is this possible in JSONPath?
I've tried variations on $.content[?(#.iteration_size == 1)].iteration_size, but the two online evaluators I've tried even disagree on the results of several of my attempts.
The use case is the AWS Batch API, where the array size must be either null or a number between 2 and 10,000.
AWS Support suggested that this was not possible, and that I should instead use a branch in the step function. I ended up replacing this:
.next(batch_submit_job)
[…]
with this:
.next(
aws_stepfunctions.Choice(self, "check_maybe_array")
.when(
aws_stepfunctions.Condition.number_equals("$.content.iteration_size", 1),
single_batch_submit_job,
)
.otherwise(array_batch_submit_job)
.afterwards()
)
where only array_batch_submit_job has an array_size. Note how the rest of the step function ended up wrapped inside the last next() call rather than at the top level.

Decoding and using JSON data in Perl

I am confused about accessing the contents of some JSON data that I have decoded. Here is an example
I don't understand why this solution works and my own does not. My questions are rephrased below
my $json_raw = getJSON();
my $content = decode_json($json_raw);
print Data::Dumper($content);
At this point my JSON data has been transformed into this
$VAR1 = { 'items' => [ 1, 2, 3, 4 ] };
My guess tells me that, once decoded, the object will be a hash with one element that has the key items and an array reference as the value.
$content{'items'}[0]
where $content{'items'} would obtain the array reference, and the outer $...[0] would access the first element in the array and interpret it as a scalar. However this does not work. I get an error message use of uninitialized value [...]
However, the following does work:
$content->{items}[0]
where $content->{items} yields the array reference and [0] accesses the first element of that array.
Questions
Why does $content{'items'} not return an array reference? I even tried #{content{'items'}}, thinking that, once I got the value from content{'items'}, it would need to be interpreted as an array. But still, I receive the uninitialized array reference.
How can I access the array reference without using the arrow operator?
Beginner's answer to beginner :) Sure not as profesional as should be, but maybe helps you.
use strict; #use this all times
use warnings; #this too - helps a lot!
use JSON;
my $json_str = ' { "items" : [ 1, 2, 3, 4 ] } ';
my $content = decode_json($json_str);
You wrote:
My guess tells me that, once decoded, the object will be a hash with
one element that has the key items and an array reference as the value.
Yes, it is a hash, but the the decode_json returns a reference, in this case, the reference to hash. (from the docs)
expects an UTF-8 (binary) string and tries to parse that
as an UTF-8 encoded JSON text,
returning the resulting reference.
In the line
my $content = decode_json($json_str);
you assigning to an SCALAR variable (not to hash).
Because you know: it is a reference, you can do the next:
printf "reftype:%s\n", ref($content);
#print: reftype:HASH ^
#therefore the +------- is a SCALAR value containing a reference to hash
It is a hashref - you can dump all keys
print "key: $_\n" for keys %{$content}; #or in short %$content
#prints: key: items
also you can assing the value of the "items" (arrayref) to an scalar variable
my $aref = $content->{items}; #$hashref->{key}
#or
#my $aref = ${$content}{items}; #$hash{key}
but NOT
#my $aref = $content{items}; #throws error if "use strict;"
#Global symbol "%content" requires explicit package name at script.pl line 20.
The $content{item} is requesting a value from the hash %content and you never defined/assigned such variable. the $content is an scalar variable not hash variable %content.
{
#in perl 5.20 you can also
use 5.020;
use experimental 'postderef';
print "key-postderef: $_\n" for keys $content->%*;
}
Now step deeper - to the arrayref - again you can print out the reference type
printf "reftype:%s\n", ref($aref);
#reftype:ARRAY
print all elements of array
print "arr-item: $_\n" for #{$aref};
but again NOT
#print "$_\n" for #aref;
#dies: Global symbol "#aref" requires explicit package name at script.pl line 37.
{
#in perl 5.20 you can also
use 5.020;
use experimental 'postderef';
print "aref-postderef: $_\n" for $aref->#*;
}
Here is an simple rule:
my #arr; #array variable
my $arr_ref = \#arr; #scalar - containing a reference to #arr
#{$arr_ref} is the same as #arr
^^^^^^^^^^ - array reference in curly brackets
If you have an $arrayref - use the #{$array_ref} everywhere you want use the array.
my %hash; #hash variable
my $hash_ref = \%hash; #scalar - containing a reference to %hash
%{$hash_ref} is the same as %hash
^^^^^^^^^^^ - hash reference in curly brackets
If you have an $hash_ref - use the %{$hash_ref} everywhere you want use the hash.
For the whole structure, the following
say $content->{items}->[0];
say $content->{items}[0];
say ${$content}{items}->[0];
say ${$content}{items}[0];
say ${$content->{items}}[0];
say ${${$content}{items}}[0];
prints the same value 1.
$content is a hash reference, so you always need to use an arrow to access its contents. $content{items} would refer to a %content hash, which you don't have. That's where you're getting that "use of uninitialized value" error from.
I actually asked a similar question here
The answer:
In Perl, a function can only really return a scalar or a list.
Since hashes can be initialized or assigned from lists (e.g. %foo = (a => 1, b => 2)), I guess you're asking why json_decode returns something like { a => 1, b => 2 } (a reference to an anonymous hash) rather than (a => 1, b => 2) (a list that can be copied into a hash).
I can think of a few good reasons for this:
in Perl, an array or hash always contains scalars. So in something like { "a": { "b": 3 } }, the { "b": 3 } part has to be a scalar; and for consistency, it makes sense for the whole thing to be a scalar in the same way.
if the hash is quite large (many keys at top-level), it's pointless and expensive to iterate over all the elements to convert it into a list, and then build a new hash from that list.
in JSON, the top-level element can be either an object (= Perl hash) or an array (= Perl array). If json_decode returned a list in the former case, it's not clear what it would return in the latter case. After decoding the JSON string, how could you examine the result to know what to do with it? (And it wouldn't be safe to write %foo = json_decode(...) unless you already knew that you had a hash.) So json_decode's behavior works better for any general-purpose library code that has to use it without already knowing very much about the data it's working with.
I have to wonder exactly what you passed as an array to json_decode, because my results differ from yours.
#!/usr/bin/perl
use JSON qw (decode_json);
use Data::Dumper;
my $json = '["1", "2", "3", "4"]';
my $fromJSON = decode_json($json);
print Dumper($fromJSON);
The result is $VAR1 = [ '1', '2', '3', '4' ];
Which is an array ref, where your result is a hash ref
So did you pass in a hash with element items which was a reference to an array?
In my example you would get the array by doing
my #array = #{ $fromJSON };
In yours
my #array = #{ $content->{'items'} }
I don't understand why you dislike the arrow operator so much!
The decode_json function from the JSON module will always return a data reference.
Suppose you have a Perl program like this
use strict;
use warnings;
use JSON;
my $json_data = '{ "items": [ 1, 2, 3, 4 ] }';
my $content = decode_json($json_data);
use Data::Dump;
dd $content;
which outputs this text
{ items => [1 .. 4] }
showing that $content is a hash reference. Then you can access the array reference, as you found, with
dd $content->{items};
which shows
[1 .. 4]
and you can print the first element of the array by writing
print $content->{items}[0], "\n";
which, again as you have found, shows just
1
which is the first element of the array.
As #cjm mentions in a comment, it is imperative that you use strict and use warnings at the start of every Perl program. If you had those in place in the program where you tried to access $content{items}, your program would have failed to compile, and you would have seen the message
Global symbol "%content" requires explicit package name
which is a (poorly-phrased) way of telling you that there is no %content so there can be no items element.
The scalar variable $content is completely independent from the hash variable %content, which you are trying to access when you write $content{items}. %content has never been mentioned before and it is empty, so there is no items element. If you had tried #{$content->{items}} then it would have worked, as would #{${$content}{items}}
If you really have a problem with the arrow operator, then you could write
print ${$content}{items}[0], "\n";
which produces the same output; but I don't understand what is wrong with the original version.

Delphi SuperObject sorting values in a different order than added

I'm using SuperObject to produce JSON. The server I'm working with has some specifications for sorting data results (the fact that this is related to sorting data has nothing to do with my actual question about sorting). The thing is, the server expects these values to be listed in order of how to sort, so for example...
"sort": {
"first_sort_field": 1,
"second_sort_field": 1,
"third_sort_field": -1,
"fourth_sort_field": 1
}
1 means ascending and -1 means descending. But that's not the important part. What's important is that these values in the sort object must be organized in this manner.
To produce this object, I'm doing this:
var
O, O2: ISuperObject;
X: Integer;
//more
begin
O:= SO; //main object
//more
O2:= SO; //sub object
for X := 0 to FSort.Count - 1 do begin
case FSort[X].Direction of
sdAscending: O2.I[FSort[X].FieldName]:= 1;
sdDescending: O2.I[FSort[X].FieldName]:= -1;
end;
end;
O.O['sort']:= O2;
//more
end;
The problem arises when I use SuperObject to serialize this "sort" object. The values seem to be re-arranged, so for example the JSON above would actually come out something like this:
"sort": {
"first_sort_field": 1,
"fourth_sort_field": 1
"second_sort_field": 1,
"third_sort_field": -1,
}
Which is a different order than I intended. This causes the server to return the response data sorted in a different manner than intended.
The question is, how can I make SuperObject serialize the data in the order which I added it rather than its own order? I thought that it might be sorting the values in ABC order, but when combining different types of values (string, integer, object, array, etc.) they're not in ABC order. I'd like to force SuperObject to serialize the data in the order which I added it.
The only solution I can see is to serialize this object manually by concatenating strings. But I'd like to avoid that if at all possible - that's why I'm using SuperObject in the first place.
The documentation for JSON states that its dictionary object is unordered:
An object is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are separated by , (comma).
By way of contrast, the JSON array is ordered:
An array is an ordered collection of values. An array begins
with [ (left bracket) and ends with ] (right bracket). Values
are separated by , (comma).
If you want to persist the order of your keys, you will need to do so separately from the dictionary. Any program that expresses meaning by the order in which name/value pairs are written falls outside the JSON spec. So, if your server relies on the order, then that makes the file no longer a JSON file.
Order is clearly important here. And so the solution is clear. Use the ordered data type, the array. Your JSON should be:
"sort": [
{ "name": "first_sort_field", "order": 1 },
{ "name": "second_sort_field", "order": 1 },
.....
]

Efficient parsing of first four elements of large JSON arrays

I am using Jackson to parse JSON from a json inputStream which looks like following:
[
[ 36,
100,
"The 3n + 1 problem",
56717,
0,
1000000000,
0,
6316,
0,
0,
88834,
0,
45930,
0,
46527,
5209,
200860,
3597,
149256,
3000,
1
],
[
........
],
[
........
],
.....// and almost 5000 arrays like above
]
This is the original feed link: http://uhunt.felix-halim.net/api/p
I want to parse it and keep only the first 4 elements of every array and skip other 18 elements.
36
100
The 3n + 1 problem
56717
Code structure I have tried so far:
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
jsonParser.nextToken(); // '['
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
// I tried many approaches here but not found appropriate one
}
}
As this feed is pretty big, I need to do this efficiently with less overhead and memory.
Also there are three models to procress JSON: Streaming API, Data Binding and Tree Model. Which one is appropriate for my purpose?
How can I parse this json efficiently with Jackson? How can I skip those 18 elements and jump to next array for better performance?
Edit: (Solution)
Jackson and GSon both works in almost in the same mechanism (incremental mode, since content is read and written incrementally), I am switching to GSON as it has a function skipValue() (pretty appropriate with name). Although Jackson's nextToken() will work like skipValue(), GSON seems more flexible to me. Thanks #Kowser bro for his recommendation, I came to know about GSON before but somehow ignored it. This is my working code:
reader.beginArray();
while (reader.hasNext()) {
reader.beginArray();
int a = reader.nextInt();
int b = reader.nextInt();
String c = reader.nextString();
int d = reader.nextInt();
System.out.println(a + " " + b + " " + c + " " + d);
while (reader.hasNext())
reader.skipValue();
reader.endArray();
}
reader.endArray();
reader.close();
This is for Jackson
Follow this tutorial.
Judicious use of jasonParser.nextToken() should help you.
while (jasonParser.nextToken() != JsonToken.END_ARRAY) { // might be JsonToken.START_ARRAY?
The pseudo-code is
find next array
read values
skip other values
skip next end token
This is for gson.
Take a look at this tutorial. Consider following second example from the tutorial.
Judicious use of reader.begin* reader.end* and reader.skipValue should do the job for you.
And here is the documentation for JsonReader

How to look ahead in a mysql result

I have an array containing the results of a mysql query on "Category", "Group" and "Subgroup" for stock items. I need to build a dynamic menu but the content of the current line of the array I am building depends on a column in the next line.
I have looked up and found many examples but all of them check the whole line of the array (the mysql row) I only want to check one item in the line of the array (one mysql column). I need something like
for ( $ix = 0; $ix < (length(current_result) - 1); $ix++) {
if (current_result[$ix, Catagory] = current_result[$ix + 1, Catagory]) {
echo some code
} else {
echo some other code
}
}
some code to handle the last line of the array
Assuming you have an associative array of rows, you're simply missing proper array syntax:
for( .... ){
$thiscat = $current_result[$ix]['Category'];
$nextcat = $current_result[$ix+1]['Category'];
}