Using Sortby and Echo together - sorting

I have been trying to find a way to echo the values of a variable while their being sorted. Is there a way to do this without having to wait until all the values of that variable are already sorted? For example:
SORTBY (#FileName DESCENDING)
But I want to echo the value of each filename as it's being sorted. I was thinking of for or do loop but that didn't seem to work.

Related

How to break FOR loop in simulink

In Simulink, I have a signal that is a 1-D array.
I want to get the index of the first value other than 0, but the result received is the index of the last non-zero value
I am new to Simulink, is there any way to break FOR loop?
Or what should I do in this case
Any hint will be great.
Thanks.
Rather than using a for loop iterator subsystem, use the while iterator subsystem.
From the properties you can enable the "Show iteration number port" option to give you the index to increment over the items in the array.
The while iterator also has a "cond" or condition input which you can set to exit the while loop when you get to a non-zero value.
Alternatively, use the for loop but work from the end of the array towards the front and output the last non-zero value which will be the first non-zero value if you worked in a forwards direction.
Use the length minus the index value to access the array to work backwards.

How do I prevent to operate over an empty matrix or a matrix with empty columns or row?

In the problem that I want to solve a well defined matrix has no empty rows or columns.
For example the matrix [[],[]] is not valid.
When I call the function first_column, how do I prevent to execute it if the matrix that I send as an argument is not valid as defined before?
first_column([],[],[]).
first_column([[H|T]|Tail],[H|Col],[T|Rows]):- first_column(Tail,Col,Rows).
Technically, what you're asking can be done by testing for an end-condition of a list with one element, rather than an empty list, based on the specs you gave.
first_column([[H|T]],[H],[T]).
first_column([[H|T]|Tail],[H|Col],[T|Rows]):- first_column(Tail,Col,Rows).
However, beyond your specs, I suspect that you'll also need to "transfer" your final Col,Rows to end variables, something like:
first_column([[H|T]],C,R,[H|C],[T|R]).
first_column([[H|T]|Tail],[H|C],[T|R],Col,Rows):-
first_column(Tail,C,R,Col,Rows).
The modified predicate would be called with initial conditions, like
first_column(List,[],[],Col,Rows).

nested associative arrays in bash [duplicate]

This question already has answers here:
Multidimensional associative arrays in Bash
(2 answers)
Closed 2 years ago.
Can one construct an associative array whose elements contain arrays in bash? For instance, suppose one has the following arrays:
a=(a aa)
b=(b bb bbb)
c=(c cc ccc cccc)
Can one create an associate array to access these variables? For instance,
declare -A letters
letters[a]=$a
letters[b]=$b
letters[c]=$c
and then access individual elements by a command such as
letter=${letters[a]}
echo ${letter[1]}
This mock syntax for creating and accessing elements of the associate array does not work. Do valid expressions accomplishing the same goals exist?
This is the best non-hacky way to do it but you're only limited to accessing single elements. Using indirect variable expansion references is another but you'd still have to store every element set on an array. If you want to have some form of like anonymous arrays, you'd need to have a random parameter name generator. If you don't use a random name for an array, then there's no sense referencing it on associative array. And of course I wouldn't like using external tools to generate random anonymous variable names. It would be funny whoever does it.
#!/bin/bash
a=(a aa)
b=(b bb bbb)
c=(c cc ccc cccc)
declare -A letters
function store_array {
local var=$1 base_key=$2 values=("${#:3}")
for i in "${!values[#]}"; do
eval "$1[\$base_key|$i]=\${values[i]}"
done
}
store_array letters a "${a[#]}"
store_array letters b "${b[#]}"
store_array letters c "${c[#]}"
echo "${letters[a|1]}"
I think the more straightforward answer is "No, bash arrays cannot be nested."
Anything that simulates nested arrays is actually just creating fancy mapping functions for the keyspace of the (single layered) arrays.
Not that that's bad: it may be exactly what you want, but especially when you don't control the keys into your array, doing it properly becomes harder.
Although I like the solution given by #konsolebox of using a delimiter, it ultimately falls over if your keyspace includes keys like "p|q".
It does have a nice benefit in that you can operate transparently on your keys, as in array[abc|def] to look up the key def in array[abc], which is very clear and readable.
Because it relies on the delimiter not appearing in the keys, this is only a good approach when you know what the keyspace looks like now and in all future uses of the code. This is only a safe assumption when you have strict control over the data.
If you need any kind of robustness, I would recommend concatenating hashes of your array keys. This is a simple technique that is extremely likely to eliminate conflicts, although they are possible if you are operating on extremely carefully crafted data.
To borrow a bit from how Git handles hashes, let's take the first 8 characters of the sha512sums of keys as our hashed keys.
If you feel nervous about this, you can always use the whole sha512sum, since there are no known collisions for sha512.
Using the whole checksum makes sure that you are safe, but it is a little bit more burdensome.
So, if I want the semantics of storing an element in array[abc][def] what I should do is store the value in array["$(keyhash "abc")$(keyhash "def")"] where keyhash looks like this:
function keyhash () {
echo "$1" | sha512sum | cut -c-8
}
You can then pull out the elements of the associative array using the same keyhash function.
Funnily, there's a memoized version of keyhash you can write which uses an array to store the hashes, preventing extra calls to sha512sum, but it gets expensive in terms of memory if the script takes many keys:
declare -A keyhash_array
function keyhash () {
if [ "${keyhash_array["$1"]}" == "" ];
then
keyhash_array["$1"]="$(echo "$1" | sha512sum | cut -c-8)"
fi
echo "${keyhash_array["$1"]}"
}
A length inspection on a given key tells me how many layers deep it looks into the array, since that's just len/8, and I can see the subkeys for a "nested array" by listing keys and trimming those that have the correct prefix.
So if I want all of the keys in array[abc], what I should really do is this:
for key in "${!array[#]}"
do
if [[ "$key" == "$(keyhash "abc")"* ]];
then
# do stuff with "$key" since it's a key directly into the array
:
fi
done
Interestingly, this also means that first level keys are valid and can contain values. So, array["$(keyhash "abc")"] is completely valid, which means this "nested array" construction can have some interesting semantics.
In one form or another, any solution for nested arrays in Bash is pulling this exact same trick: produce a (hopefully injective) mapping function f(key,subkey) which produces strings that they can be used as array keys.
This can always be applied further as f(f(key,subkey),subsubkey) or, in the case of the keyhash function above, I prefer to define f(key) and apply to subkeys as concat(f(key),f(subkey)) and concat(f(key),f(subkey),f(subsubkey)).
In combination with memoization for f, this is a lot more efficient.
In the case of the delimiter solution, nested applications of f are necessary, of course.
With that known, the best solution that I know of is to take a short hash of the key and subkey values.
I recognize that there's a general dislike for answers of the type "You're doing it wrong, use this other tool!" but associative arrays in bash are messy on numerous levels, and run you into trouble when you try to port code to a platform that (for some silly reason or another) doesn't have bash on it, or has an ancient (pre-4.x) version.
If you are willing to look into another language for your scripting needs, I'd recommend picking up some awk.
It provides the simplicity of shell scripting with the flexibility that comes with more feature rich languages.
There are a few reasons I think this is a good idea:
GNU awk (the most prevalent variant) has fully fledged associative arrays which can nest properly, with the intuitive syntax of array[key][subkey]
You can embed awk in shell scripts, so you still get the tools of the shell when you really need them
awk is stupidly simple at times, which puts it in stark contrast with other shell replacement languages like Perl and Python
That's not to say that awk is without its failings. It can be hard to understand when you're first learning it because it's heavily oriented towards stream processing (a lot like sed), but it's a great tool for a lot of tasks that are just barely outside of the scope of the shell.
Note that above I said that "GNU awk" (gawk) has multidimensional arrays. Other awks actually do the trick of separating keys with a well-defined separator, SUBSEP. You can do this yourself, as with the array[a|b] solution in bash, but nawk has this feature builtin if you do array[key,subkey]. It's still a bit more fluid and clear than bash's array syntax.
For those stumbling on this question when looking for ways to pass command line arguments within a command line argument, an encoding such as JSON could turn useful, as long as the consumer agrees to use the encoding.
# Usage: $0 --toolargs '["arg 1", "arg 2"]' --otheropt
toolargs="$2"
v=()
while read -r line; do v+=("${line}"); done < <(jq -r '.[]' <<< "${toolargs}")
sometool "${v[#]}"
nestenc='{"a": ["a", "aa "],
"b": ["b", "bb", "b bb"],
"c d": ["c", "cc ", " ccc", "cc cc"]
}'
index="c d"
letter=()
while read -r line; do
letter+=("${line}")
done < <(jq -r ".\"${index}\"[]" <<< "${nestenc}")
for c in "${letter[#]}" ; do echo "<<${c}>>" ; done
The output follows.
<<c>>
<<cc>>
<<ccc>>
<<cc cc>>

Is there a way to store a list when programming a TI-83+?

Out of curiosity, I'm beginning to learn how to program my TI-83+ calculator. Part of my latest program involves storing numbers in a list. How can I add items to a list on a TI-83+ and how can I loop over them/access them?
Well, if you want to add something to the end, you need the length of the list. Let's say your using L1 as a list and variable A as the value you are trying to add to the list.
Here's what you would do:
:A->L1(1+dim(L1))
Here's how that works. The dim command has 1 parameter. That parameter is a list. When you use the dim command, it returns the length of the list in the parameters. When you want to refer to a specific place in a list, you use the syntax: list_name(location). So This line of code takes the value of variable A and stores it in the location of L1 which is 1 more than the length of L1, therefore appending variable A to the end of L1.
If you want to access a value in list, again use the syntax: list_name(location). On the other hand, if you don't know the location of the value you are looking for, or you are cycling through the list and doing something with each value, you can use a for statement.
Like this:
:FOR(A, 0, dim(L1))
::L1(A)->B
::"do whatever you want with the value of L1(A) here"
:END
Or like this:
:FOR(A, 0, dim(L1))
::if(L1(A) == "insert value being searched for here"):THEN
:::A->B
:::dim(L1)+1->A
::END
:END
The for loop works like this: at the beginning of the loop, 0 is stored to variable A. Then the loop continues until variable A is greater than dim(L1). After each time the loop resets, the value of variable A is increased by 1.
In the first example, the program loops through each value of L1 and does whatever you want to do with each value.
In the second example, the program loops through each value of L1. When the value of L1 matches the value you are looking for, the location of the value is stored in variable B to be used for whatever you want later. Then, the value of variable A is set to 1 more than the length of L1. Since the value of variable A is greater than dim(L1), the for loop is terminated.
An element can be added to the end of a list of unknown length like this:
0→L1(1+dim(L1
Under normal condition, attempting to set the value of an index greater than the length of the list results in ERR: INVALID DIM; however, if the index is only 1 greater than the length of the list, the value is appended to the end of the list.
You could use a list or a matrix, but I would suggest a list. You can find information on lists and their commands from this link.
Lists are also better for saving values in between program executions than just using variables, which may be changes by other programs or math.
You need first to define the size of a list like this :
3->dim(L1
(if you forget, you will have an ERR:Invalid Dim)
Press enter and you get a "10" as answer (don't worry it's normal).
You can find dim( in the [Catalog] and -> is "[STO->].
Then you could fill the list with some data like this :
2->L1(1)
3->L1(3)
Now When you print L1 you get :
{2 0 3 0}
First index is L1(1) not 0 (as usual).
You can delete the list by using DelVar :
DelVar L1
You can fill it with Fill, sort it, convert to matrix ....
Simply go to the List menu (2nd + Stat).
You can iterate on the list using a for loop (no foreach, use dim(L1) for the upper bound).
More informations in the guidebook or you could also ask your questions on this calculator questions stack
Hope this helps =)
You can do what Thibault said, fill it, sort it, convert it (Very well said, by the way). However, you can also do:
3->L1(dim(L1))
This will add 3 to the end of L1.

Difference between foreach and iterate in smarty

What is difference between {iterate} and {foreach} in smarty tpl files?
are they different in using 'from' phrase?
As far as I know, there is no command called "iterate" in Smarty. There is, however, a command called {section} that is often confused with {foreach}.
From the documentation at Smarty.net:
The {foreach} loop can do everything a {section} loop can do, and has
a simpler and easier syntax. It is usually preferred over the
{section} loop.
Also:
{section} loops cannot loop over associative arrays, they must be
numerically indexed, and sequential (0,1,2,...). For associative
arrays, use the {foreach} loop.
Hopefully that helps.

Resources