I have few functions in my system that should be converted from CFML to CFSCRIPT. While working on this project I run to the situation where my structure outputs more result (a lot of empty rows) than it should, even query returns only one row. Here is example of my code in CFSCRIPT:
cfstoredproc( procedure="GetZip", datasource=Application.dsnRead ) {
cfprocparam( dbvarname="#Zip", value=trim(52401), cfsqltype="cf_sql_char", maxlength=5 );
cfprocresult( name="ZipResult" );
}
local.strZip = {};
strZip[ZipResult.RecID] = {
"City" : trim(ZipResult.City),
"State" : trim(ZipResult.State)
};
writeDump(strZip);
Here is what I get for the output:
array
1 [undefined array element]
2 [undefined array element]
3 [undefined array element]
4 [undefined array element]
5 [undefined array element]
6 [undefined array element]
7 [undefined array element]
8 [undefined array element]
9 [undefined array element]
10 [undefined array element]
11 [undefined array element]
12 [undefined array element]
13 [undefined array element]
14 [undefined array element]
...
I'm wondering what is the best way to output query result(s) in structure and use RecID as a unique key? This example and query above always will return 1 record at the time but also I'm wondering how this code would work if I need to loop over the query result with multiple records?
Update: I think that I found the problem. The RecID is auto increment id in my db table. When i return RecID the value can be 56743 for example. So if I pass RecID as a key in my structure, that will cause so many rows in the structure. My question is how to prevent this? Is there a way to just set the key?
I'm not sure why your CF is converting strZip to an array, but that is why you are getting a bunch of empties. A structure key can be an integer, but when you tell an array to insert x[42], you will have 42 elements in your array. local.strZip = {}; pretty explicitly states that strZip is a struct. However, scopes can get weird in CF sometimes. Depending on how you're using it, I think when you do strZip[ZipResult.RecID] it may be creating a new unscoped variable that is an array. And then when you dump it, you are dumping the array version of strZip. You can try using local.strZip[ZipResult.RecID] and see if that changes your behavior. Or try dumping local.strZip and see if it's empty.
Or you can do:
<cfscript>
// Build a fake query object.
ZipResult = queryNew(
"RecID, City, State",
"integer, varchar, varchar",
[
{ RecID: 99, City: "Nashville", State: "TN" }
]
);
writeDump(ZipResult); // What's in our query?
local.strZip = {
"#ZipResult.RecID#" : {
City : trim(ZipResult.City) ,
State : trim(ZipResult.State)
}
};
writeDump(strZip);
</cfscript>
https://trycf.com/gist/28440630b0aa7ba1642e45bab3503652/acf2016?theme=monokai
NOTE: I was unable to duplicate your behavior in TryCF, but I'm also not likely executing that code in the same scope that you are.
CONFIRMED: https://cffiddle.org/app/file?filepath=50f4e710-bd9b-40dd-a03a-15695bdd5a0d/c476f91b-6931-4295-be67-e4309aecfa0c/0492a7c6-029f-4227-941a-faee9da5a7cc.cfm
You can try this -
var strZip = {};
for ( i=1; i<=ZipResult.recordCount; i++)
{
strZip[ZipResult.RecID[i]] = {
"City" : trim(ZipResult.City[i]),
"State" : trim(ZipResult.State[i])
};
}
This way we are treating query like a structure of arrays.
No, you're right. Because it's an integer, ColdFusion is populating the array up to the point of that integer since you can't have an array with a bunch of empty values; they have to have some value, so - as you see here - they're undefined.
You can't use an integer for a struct key. If you add a letter to the front of it, then chop the key to that value when you reference it, that will work. It's hacky, but that's what I generally do for this sort of thing.
If you want to test it, you could use StructInsert() instead of [].
Related
new Array(n) will create an array of n * undefined, so why can't you use new Array(n).map((_, index) => index) function to get [0, 1, 2 ..., n-1 ] What about arrays like this?
I know that new Array(n).fill(0).map((_, index) => index) is ok, but is there any essential difference between the two arrays of n * undefined and n * 0 ?
Common pits for initializing an n*m two-dimensional array:
Wrong way 1: new Array(n).fill(new Array(m).fill(0)) All arrays point to the same reference
Wrong way 2: new Array(n).map(v => new Array(m).fill(0)) "ghost array" problem
Correct way 1: new Array(n).fill(0).map(v => new Array(m).fill(0))
From the MDN Web Docs:
If the only argument passed to the Array constructor is an integer [...] this returns a new JavaScript array with its length property set to that number (Note: this implies an array of arrayLength empty slots, not slots with actual undefined values)
So like they say, it just sets the length, it doesn't set any of the values. So if the array contains no elements, then you can't map a non-existent value into a function.
Array Document
If the only argument passed to the Array constructor is an integer between 0 and 2^32 - 1 (inclusive), this returns a new JavaScript array with its length property set to that number (Note: this implies an array of arrayLength empty slots, not slots with actual undefined values — see sparse arrays). If the argument is any other number, a RangeError exception is thrown.
Array(n) or new Array(n) produces arrays with only length and no elements, so I call them "ghost arrays". Such an array cannot be traversed correctly with forEach or map (because there are no elements), but it is amazing that it has [##iterator], which can be traversed using for ... of, or expanded into an array using the spread operator (eg [...Array(10)]), and can be converted using Array.from().
I would like to find documents with a mango query by specifying the minimal and maximal size of an array property. Given a document with an array property customers. I'd like to be able to find all documents with the number of customers between 10 and 20.
Something like
mango_query = {
"doc.customers": {"$size": {"gte": 10}},
"doc.customers": {"$size": {"lte": 20}}
}
The response to a request like that is
Bad argument for operator $size: {[{<<36,108,116,101>>,10}]}')
So how should I write a mango filter on the size of an array?
Checking the code here, only integer argument is supported for $size operator. So it can't be combined with other operators. It supports only $size exact matches.
norm_ops({[{<<"$size">>, Arg}]}) when is_integer(Arg), Arg >= 0 ->
{[{<<"$size">>, Arg}]};
norm_ops({[{<<"$size">>, Arg}]}) ->
?MANGO_ERROR({bad_arg, '$size', Arg});
And when matching
match({[{<<"$size">>, Arg}]}, Values, _Cmp) when is_list(Values) ->
length(Values) == Arg;
match({[{<<"$size">>, _}]}, _Value, _Cmp) ->
false;
length(Values) == Arg Only exact match is supported
This question already has answers here:
How to slice a struct array?
(4 answers)
Closed 2 years ago.
How can I get all values of a complete column (fieldname), for all rows, from an Octave struct?
I would get it into a cell array, or a regular vector, preferably without looping.
You seem to be confusing a few things. Partly because of your equivalence comparison of structs to "R dataframes / python pandas".
Structs are better thought of as being similar to python dicts, R lists, etc. They are a special object that can hold 'fields', which can be accessed by a 'fieldname' ( or values accessed by keys, if you prefer ).
Also, like any other object in octave, they are valid elements for an array. This means you can have something like this:
octave:1> struct( 'name', { 'Tom', 'Jim'; 'Ann', 'Sue' }, 'age', { 20, 21; 22, 23 } )
S =
2x2 struct array containing the fields:
name
age
In general, when one deals with such a struct array, accessing a field on more than one elements of the array, produces a comma separated list. E.g.
octave:6> S(2,:).name
ans = Ann
ans = Sue
This can be passed to (i.e. "expanded into") any function that expects such a comma separated list as arguments. E.g.
octave:7> fprintf( 'The girls names are %s, and %s.\n', S(2,:).name )
The girls names are Ann, and Sue.
If you want, you can also pass that list straight into a 'cell constructor', to create a cell. (though if you want it to have a particular shape, you'll have to reshape it afterwords). E.g.
octave:9> reshape( { S.age }, size(S) )
ans =
{
[1,1] = 20
[2,1] = 22
[1,2] = 21
[2,2] = 23
}
There is also struct2cell but this does something different. Try it to see what it does (e.g. C = struct2cell(S) ).
Finally, to avoid confusion, given the fact that when one deals with struct arrays, "columns" refer to columns in the 'array', I would avoid referring to "fieldnames" by that term.
How can I assign each document in a collection C a unique value from an array?
Let's say I create the array let A = 1..count(C). How can I give each document in C a number from A, making sure each element of A is used only once?
There's are unfortunately no Python-like iterators enumerate() and zip() in AQL, which would make this really easy and efficient. It is still possible however, but can be a costly operation (mainly memory-intense) for very large datasets, because all document keys need to be fetched and stored in memory:
LET arr = RANGE(1, LENGTH(C) * 2, 2)
LET docs = (FOR doc IN C RETURN doc._key)
FOR n IN 0..LENGTH(docs)-1
UPDATE docs[n] WITH {number: arr[n]} IN test
RETURN NEW
An array arr is generated (here: as many odd numbers as there are documents in the collection C), and a variable docs holds all document keys of C. A loop over the range 0..n with n = number of documents in C is used for a counter n. Then, the nth document key of docs is used to update a document with the nth number from the array arr.
If you want to assign A = 1..LENGTH(C), then a slightly simpler query can be used:
LET docs = (FOR doc IN C RETURN doc._key)
FOR n IN 1..LENGTH(docs)
UPDATE docs[n-1] WITH {number: n} IN test
RETURN NEW
So I was getting a notice in my php while creating a google product feed.
The notice was
"The following php notice has occurred 4989 times on the _ site today:
PHP Notice: Undefined index: 0 in /xxx/Status.php on line 583"
This was the code in that class
public function inStockLocally($productcode)
{
if($this->_status[$productcode]['status'] == self::IN_STOCK) {
return $this->_status[$productcode]['in_stock_local'];
}
return false;
}
The function was getting a $productcode = 0, but the productcode was infact 'w32', so the key didn't exist.
up the stack where the function was being called I put this in, in order to break on the troublesome product.
if ($productcode == 0) {
$test = 'breakhere';
}
Using netbeans and firebug, it broke on the line when $productcode = 'w32'
So my question is why does 'w32' == 0 evaluate to true?
It is also evaluating to true with other similar structure codes like 'h94'.
Any help would be appreciated as no one in the department can figure out why this is happening.
I guess I didn't put enough info in the q. Two things going on.
1. 'w32' converted to a number = 0 for some reason. 2. [0] is being inserted as my key in the array when the productcode has the structure 'x##';
I'm a little new here, so pardon if this isn't the answer you were expecting, but PHP does a lot of automatic type conversion. So any string that doesn't start with a numeric character (0..9, +, -, etc) will evaluate to zero.
"If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically. "
http://php.net/manual/en/language.operators.comparison.php
Additionally, I suppose you have an indexed array, although you expect it to be an associative array:
The array() function is used to create an array.
In PHP, there are three types of arrays:
Indexed arrays - Arrays with numeric index
Associative arrays - Arrays with named keys
Multidimensional arrays - Arrays containing one or more arrays
Syntax
Syntax for indexed arrays:
array(value1,value2,value3,etc.);
Syntax for associative arrays:
array(key=>value,key=>value,key=>value,etc.);