declare -a MY_ARRAY=()
Does the declaration of array in this way in bash will initiate all the array elements to 0?
If not, How to initiate array element to 0?
Your example will declare/initialize an empty array.
If you want to initialize array members, you do something like this:
declare -a MY_ARRAY=(0 0 0 0) # this initializes an array with four members
If you want to initialize an array with 100 members, you can do this:
declare -a MY_ARRAY=( $(for i in {1..100}; do echo 0; done) )
Keep in mind that arrays in bash are not fixed length (nor do indices have to be consecutive). Therefore you can't initialize all members of the array unless you know what the number should be.
Default Values with Associative Arrays
Bash arrays are not fixed-length arrays, so you can't pre-initialize all elements. Indexed arrays are also not sparse, so you can't really use default values the way you're thinking.
However, you can use associative arrays with an expansion for missing values. For example:
declare -A foo
echo "${foo[bar]:-baz}"
This will return "baz" for any missing key. As an alternative, rather than just returning a default value, you can actually set one for missing keys. For example:
echo "${foo[bar]:=baz}"
This alternate invocation will not just return "baz," but it will also store the value into the array for later use. Depending on your needs, either method should work for the use case you defined.
Yes, it initiates an empty array and assigns it to MY_ARRAY. You could verify with something like this:
#!/bin/bash
declare -a MY_ARRAY=()
echo ${#MY_ARRAY} # this prints out the length of the array
Related
I do not understand why $test is '1' and not 'foo'. Is there any way to write 'foo' (written in %hash) to $test?
#/usr/bin/perl
use warnings;
use strict;
use utf8;
my %hash;
$hash{'test'} = {'foo' => 1};
print keys %{$hash{'test'}}; #foo
print "\n";
print values %{$hash{'test'}}; #1
print "\n";
print %{$hash{'test'}}; #foo1
print "\n";
# here is the part I do not understand
my $test = keys %{$hash{'test'}};
print "$test\n"; #1 but why? I was expecting #foo
How can I push 'foo' in $test?
keys() returns a list. But your assignment to a scalar (my $test = keys ...) puts it into scalar context. Therefore it is evaluated to the length of the list, which is 1 in your case.
my $test = keys %{$hash{'test'}};
When assigning a list like keys returns to a scalar, what's assigned is the length of the list. Which is 1 in this case.
When the return value from a Perl function confuses you, it's always worth checking the documentation for that function - paying particular attention to the section talking about how the return value varies in different contexts.
The very start of perldoc -f keys says this (emphasis mine):
keys HASH
keys ARRAY
Called in list context, returns a list consisting of all the keys of the named hash, or in Perl 5.12 or later only, the indices of an array. Perl releases prior to 5.12 will produce a syntax error if you try to use an array argument. In scalar context, returns the number of keys or indices.
You're assigning the results of the expression to a scalar variable. The expression is, therefore, evaluated in scalar context and you get the number of keys in the hash (i.e. 1).
To fix that, force the expression to be evaluated in list context by putting parentheses around the variable:
my ($test) = keys %{$hash{'test'}};
I have a list of arrays where I added many arrays but all of them are the same size. Now I want convert this list to two dimensional array. I tried in this way:
List<Array^>^ vList = gcnew List<Array^>();
//some code where I add elements to vList
array<String ^, 2> ^ anArray = gcnew array<String ^, 2>(vList->Count, 5);
anArray = vList->ToArray();
But I have got this error:
a value of type "cli::array<System::Array ^, 1> ^" cannot be assigned to an entity of type "cli::array<System::String ^, 2> ^"
I don't know how to convert it.
You're going to have to iterate and copy all of the strings individually. However, the raw type Array^ isn't that convenient to work with, so you'll need to do something about that.
Basically, what you need to do is this:
for (int outer = 0; outer < vList->Count; outer++)
{
arrayOfSomeSort^ innerArray = vList[outer];
for (int inner = 0; inner < innerArray.Length; inner++)
anArray[outer, inner] = innerArray[inner];
}
Depending on how the rest of the program is, and what objects are actually in the List, there are a few options on what to do. Here are the options I see, in order of preference.
Instead of a List<Array^>^, have vList be a List<array<String^>^>^. If the List truly is a list of string arrays, then this option is probably the most correct. In this case, arrayOfSomeSort^ would be array<String^>^.
If vList can't change type, but it does indeed contain string arrays, then I'd have the local variable innerArray be of type array<String^>^, and do a cast as you pull it out of vList.
If the arrays in the list aren't string arrays, but instead are object arrays that happen to contain strings, then I'd have array<Object^>^ innerArray, and cast to that instead, and do a cast to String^ as you pull each string out of innerArray.
If none of those is appropriate, then you can leave innerArray as type Array^. You'll need to call the explicit method Array.GetValue(int) instead of using the [] indexer. As with the previous option, you'll need to cast each string as you pull it out of the inner array.
You've set the second dimension to 5 without checking the lengths of the inner arrays; I'm assuming you know something we don't, and are sure that there won't be anything larger than 5. If not, you'll need to iterate the list once to get the maximum array size, create the 2D array, and then copy the strings.
I want to pass an empty string as one of the values to a bash for-loop – like this:
for var in "" A B C; do
...
done
This works. However, I would like to store the possible values in a variable, like this:
VARS="" A B C
for var in $VARS; do
...
Here, the empty string is ignored (or all values are concatenated if I use for var in "$VARS"). Is there an easy way to solve this?
You can't. Don't do that. Use an array.
This is a version of Bash FAQ 050.
VARS=("" A B C)
for var in "${VARS[#]}"; do
: ...
done
And you almost never want to use an unquoted variable (like for var in $VARS).
I would suggest using an array
#!/bin/bash
array=("" 1 2 "")
for i in "${array[#]}";do
echo $i
done
I would like to define a function which returns the string "NaN" or sprintf("%g",val) depending on whether val is a string or a numeric value. Initially I was trying to test if val was defined (using the gnuplot "exists" function) but it seems that I cannot pass any undefined variable to a function (an error is issued before the function is evaluated). Therefore: is there a way to test inside a function whether the argument is a string or numeric?
I search for a function isstring which I can use somehow like
myfunc(val)=(isstring(val)?"NaN":sprintf("%g",val))
The goal is to output the values of variables without risking errors in case they are undefined. However I need it as a function if I want a compact code for many variables.
Gnuplot doesn't really have the introspection abilities that many other languages have. In fact, it treats strings and numbers (at least integers) very similarly:
print "1"+2 #prints 3
a=1
print "foo".a #prints foo1
I'm not exactly sure how this is implemented internally. However, what you're asking is very tricky to get to work.
Actually, I think your first attempt (checking if a variable exists) is more sensible as type-checking in gnuplot is impossible*. You can pass the variable name to the function as a string, but the problem is that you don't seem to have a handle on the value. All seems lost -- But wait, gnuplot has an eval statement which when given a string will evaluate it. This seems great! Unfortunately, it's a statement, not a function (so it can't be used in a function -- argv!). The best solution I can come up with is to write a function which returns an expression that can be evaluated using eval. Here goes:
def exists_func(result,var)=sprintf("%s=exists('%s')?sprintf('%g',var):'NaN'",result,var,var)
Now when you want to use it, you just prefix it with eval
a=3
eval exists_func("my_true_result","a")
print my_true_result #3
eval exists_func("my_false_result","b")
print my_false_result #NaN
This goes against the grain a little bit. In most programming languages, you'd probably want to do something like this:
my_true_result=exists_func(a)
But alas, I can't figure out how to make that form work.
Of course, the same thing goes here that always goes with eval. Don't use this function with untrusted strings.
*I don't actually know that it's impossible, but I've never been able to get it to work
EDIT
In response to your comment above on the question, I think a function like this would be a little more intuitive:
def fmt(x)=(x==x)?sprintf("%g",x):"NaN"
With this function, your "sentinal/default" value should be NaN instead of "undefined", but it doesn't seem like this should make too much of a difference...(Really, if you're willing to live with "nan" instead of "NaN" you don't need this function at all -- sprintf will do just fine. (Note that this works because according to IEEE, NaN doesn't equal anything (even itself)).
You helped me a lot these days with gnuplot. I want to give you something back because I have found a solution to check if a variable is numeric or not. This helps to decide which operators can be used on it (e.g. == for numbers, eq for strings).
The solution is not very simple, but it works. It redirects gnuplot's print command to a temp file, writes the variable to the file with print myvar and evaluates the file's first line with system("perl -e '<isnumeric(line#1 in temp file)?>' ") (<> is pseudo-code). Let me know if there's room for imrpovements and let me hear your suggestions!
Example: myvar is a float. Any integer (1 or "1") or string value ("*") works too!
myvar = -2.555
# create temporary file for checking if variables are numeric
Int_tmpfle = "tmp_isnumeric_check"
# redirect print output into temp file (existing file is overwritten)
set print Int_tmpfle
# save variable's value to file
print myvar
# check if file is numeric with Perl's 'looks_like_number' function
isnumeric = system("perl -e 'use Scalar::Util qw(looks_like_number); \
open(FLE,".Int_tmpfle."); $line = < FLE >; \
if (looks_like_number($line) > 0) {print qq(y)} ' ")
# reset print output to < STDOUT> (terminal)
set print "-"
# make sure to use "," when printing string and numeric values
if (isnumeric eq "y") {print myvar," is numeric."} else {print myvar," is not numeric."}
I am noobie in Smalltak, but I need to understand some things for my thesis. What is exactly happening when creating string or any other object? For example, lets do this:
fruit <- 'apple'
When I try to inspect object fruit, I see it has 5 inst vars. If I had assigned 'pear' to fruit, it would have had 4 inst vars. So interpreter created new instance of bytestring, added required inst vars for every character and assigned them with proper values? I believe there is something more going on, but I can't find it anywhere and I don't have time to properly learn smalltalk. Can you explain it to me, or give me some link where I can find it?
Strings are objects. Objects contain instance variables and respond to messages. In Smalltalk there are basically two kinds of instance variables: named instance variables are referenced by name (like name or phoneNumber in a Person object) and indexed instance variables are referenced by numbers. String uses indexed instance variables.
Consider the following example:
fruit := String new: 5.
fruit at: 1 put: $a;
at: 2 put: $p;
at: 3 put: $p;
at: 4 put: $l;
at: 5 put: $e.
This creates a String with space for 5 characters. It then gets the fruit variable to point to that object. Then it writes 5 characters into the string. The result is the string 'apple'.
Since Strings are so commonly used, the compiler supports a special syntax to create strings at compile time.
fruit := 'apple'
In this example, 'apple' is a String literal. The Smalltalk compiler creates the string when it compiles the line. When you run the line, you will make fruit point to the string 'apple' which has 5 indexed instance variables containing Character objects.
They're not instance variables, they're positions in an indexable object, pretty similar to what happens when you create an Array or any other kind of collection.
A String, in Smalltalk, is just a Collection of Characters, where each Character is stored in the position it occupies inside the String.
Some examples to get you acquainted with Strings being just like Arrays:
'Good Morning' at: 3.
#(1 'hi' $d 5.34) at: 3.
'Good Morning' fourth.
#(1 'hi' $d 5.34) fourth.
'Good Morning' reversed.
#(1 'hi' $d 5.34) reversed.
'Good Morning' select: [ :each | each ~= $d ].
#(1 'hi' $d 5.34) select: [ :each | each ~= $d ].
As you can see, Strings are just another kind of Collection.
Strings are indexable objects, which means that they are arrays and the slots are numbered instead of "labeled" ...
First thing, is that an expression which you giving as an example does not creates a string.
It is simple assignment.
fruit := 'apple'
does not creates a string. It assigns existing string 'apple' to fruit variable.
If you want to create new strins, you should use
(Byte)String new:
similar to
Array new: ..
This is how compiler actually creating the new strings when compiling source code.