Community discussions

MikroTik App
 
royalpublishing
Frequent Visitor
Frequent Visitor
Topic Author
Posts: 50
Joined: Mon Sep 23, 2013 5:47 pm

Array Push Function

Fri Jun 13, 2014 12:53 am

I created this simple array push function but have ran into some issues. The function works fine as long as long as the array name that you pass it as the first argument already exists, the variable type equals array, and the value is not null. I would like to be able to call this function in cases where if the array doesn't already exist, to create it, and add the second parameter to it. The problem with this is since the array doesn't exist, therefore it's value equals nil and it is basically like you never added the first parameter to the function which produces wacky results.

Here is the function

ros code

# Usage: [$arrayPush <array name> <value>]
# Input an array name and a value to push to the end of the array
:global arrayPush do={
    :if ($1="") do={ :error "You did not specify an array name argument."; }
    :if ($2="") do={ :error "You did not specify a value to add to the array."; }
    :local string;
    :if ([:typeof $1]="array") do={
        :foreach item in=$1 do={ :set string ($string . "," . $item); }
        :set string ($string . "," . $2);
        :set string [:toarray $string];
        :return $string;
    } else={ :error "Argument 1 variable type was not an array."; }
}
Here is an example of what I mean

ros code

:global myVar;
:set myVar [:toarray $myVar];
:set myVar [$arrayPush $myVar "some value"];
Since $myVar is nil, the toarray function essentially does nothing and the next line has undesired results. I'm not sure exactly how to explain this but hopefully you get the picture. Any ideas on a way to work around this?

The only thing I can currently think of is to test if the array exists before I initially call the function and if not, create a variable as a string, then convert it to an array but that's a lot of extra steps.
Last edited by royalpublishing on Fri Jun 13, 2014 9:53 pm, edited 1 time in total.
 
royalpublishing
Frequent Visitor
Frequent Visitor
Topic Author
Posts: 50
Joined: Mon Sep 23, 2013 5:47 pm

Re: Array Push Function

Fri Jun 13, 2014 9:52 pm

Figured it out. If I set the variable to "" (as type string) first instead of leaving it as nil, it works as expected.

Here are the changes made to the function.

ros code

# Usage: [$arrayPush <$array name> <value>]
# Input an array name and a value to push to the end of the array
# If array doesn't already exist, you must declare the variable and set it to "" before calling the function.
:global arrayPush do={
    :if ($2="") do={ :error "You did not specify a value to add to the array."; }
    :local string;
    :if ([:typeof $1]="array" && [:len $1]>"0") do={
        :foreach item in=$1 do={ :set string ($string . "," . $item); }
        :set string ($string . "," . $2);
        :set string [:toarray $string];
        :return $string;
    } 
    :if ($1="") do={
        :set string $2;
        :set string [:toarray $string];
        :return $string;
    }
}
It works...

ros code

:global myVar "";
:set myVar [$arrayPush $myVar "yay it works"];
:put "$myVar - $[:typeof $myVar]";
 
royalpublishing
Frequent Visitor
Frequent Visitor
Topic Author
Posts: 50
Joined: Mon Sep 23, 2013 5:47 pm

Re: Array Push Function

Mon Jun 30, 2014 7:02 pm

Here is the final version of the function, I added the ability to push a value to a specific key position inside an array.

ros code

# Usage: [$arrayPush <$array name> <value> <key position to place value (0-n or -1)>]
# Input an array name, value, and the key position to push the value to. To push value to the end of the array, enter -1.
# If array doesn't already exist, you must declare the variable and set it to "" before calling the function.
:global arrayPush do={
    :if ($2="") do={ :error "You did not specify a value to add to the array."; }
    :if ($1!="" && $3="") do={ :error "You did not specify the key position to place the value in the array."; }
    :if (($3<(-1)) || (([:typeof $3]!="num") && ([:typeof $3]!="str")) || ($3>([:len $1]-1))) do={ :error "Argument 2 invalid."; }
    :local string;
    :if ([:typeof $1]="array" && $3=(-1)) do={
        :foreach item in=$1 do={ :set string ($string . "," . $item); }
        :set string ($string . "," . $2);
        :set string [:toarray $string];
        :return $string;
    } 
    :if ([:typeof $1]="array" && [:len $1]>="0") do={
        :local counter "0";
        :foreach item in=$1 do={ 
            :if ($counter!=[:tonum $3]) do={ 
                :set string ($string . "," . $item);
                :set counter ($counter+1);
            } else={ 
                :set string ($string . "," . $2); 
                :set string ($string . "," . $item); 
                :set counter ($counter+1); 
            }
        }
        :set string [:toarray $string];        
        :return $string;
    } 
    :if ($1="") do={
        :set string $2;
        :set string [:toarray $string];
        :return $string;
    }
}
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12003
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Array Push Function

Mon Jun 30, 2014 8:59 pm

Thanks for sharing!!!

I hope you like this shorter function I made for you:
# Usage: [$arrayXpush <$array name> <value> <key position to place value>]
# <$array name> is one array name, if not exist, or are not provided one array, the function work like are passed one empty array
# <value> can be any type of value, if empty simply return $array back, if $array not exist, return one empty array.
# <key position to place value> key position to push the value to
# if any number < 0, is at beginning
# if any number > length of the array is placed at the end
# if third parameter are one empty string or omitted, the default behavior are to place the value at the array end.
# if third parameter are not one number, the default behavior are to place the value at the array start.
:global arrayXpush do={

 :local arrX value=[:toarray $1];
 :if ([:len $arrX] = 0) do={ :set $arrX value=[:toarray ""]; };
 :local arrXlen value=[:len $arrX];

 :local valX value=[:tostr $2];
 :if ($valX = "") do={ :return value=$arrX; };

 :local posX value=([:tostr $3]);
 :if ($posX = "") do={ :set $posX value=($arrXlen + 1); };
 :set $posX value=([:tonum $posX] + 0);
 :if ($posX < 0) do={ :set $posX value=0; };
 :if ($posX > $arrXlen) do={ :set $posX value=$arrXlen; };

 :if ($posX = 0) do={ :return value=($valX,$arrX); };

 :if ($posX = $arrXlen) do={ :return value=($arrX,$valX); };

 :return value=([:pick $arrX 0 ($posX - 1)],$valX,[:pick $arrX ($posX - 1) $arrXlen]);

};
Now, you can try to add this ;)
# if 4th parameter are "R" and the <key position to place value> value are between array limit, the function replace the value, instead of be inserted.
:o
 
palii
just joined
Posts: 23
Joined: Sun Nov 19, 2017 6:57 pm

Re: Array Push Function

Sun Apr 28, 2019 2:04 am

Good job guys. It seems pushing values into arrays is much simpler now. For example:
:local myarray {1;2;3;4}
:set ($myarray->[:len $myarray]) 5
:log info $myarray

Outputs: 1;2;3;4;5

Just posting in case someone finds this thread.
 
User avatar
eworm
Forum Guru
Forum Guru
Posts: 1071
Joined: Wed Oct 22, 2014 9:23 am
Location: Oberhausen, Germany
Contact:

Re: Array Push Function

Mon Apr 29, 2019 4:14 pm

All this looks a bit over-complicated. The correct way is this:
:set $MyArray ($MyArray, $Value);
 
palii
just joined
Posts: 23
Joined: Sun Nov 19, 2017 6:57 pm

Re: Array Push Function

Mon Apr 29, 2019 4:22 pm

Awesome! Thanks for that. I didn't know, you could add to arrays like that (even merge other arrays!)
 
Retral
newbie
Posts: 33
Joined: Wed Jul 25, 2018 9:10 pm

Re: Array Push Function

Tue Aug 27, 2019 5:34 am

All this looks a bit over-complicated. The correct way is this:
:set $MyArray ($MyArray, $Value);
This is beautiful
 
User avatar
Jotne
Forum Guru
Forum Guru
Posts: 3300
Joined: Sat Dec 24, 2016 11:17 am
Location: Magrathean

Re: Array Push Function

Tue Aug 27, 2019 10:02 am

:local myarray {1;2;3;4}
:set $MyArray ($MyArray, $Value);
This way is more like a join of two variable, compare to work with an array.



Better way to work with arrays are like this:
{
:local myarray {type="ford";model="mustang";color="green"}
:set ( "$myarray"->"year" ) "2015"
:set ( "$myarray"->"color" ) "blue"
:put $myarray
:put ( "$myarray"->"model" )
}
color=blue;model=mustang;type=ford;year=2015
mustang
Here we do the following
1. create an array
2. add element year and set it to 2015
3. change element color to blue
4. print array
5. print model from array

This way you can work with array without know the location of the data, point to it using name.

This will fail and you get double fields.
:set $myarray ($myarray, "color=white")
Example
{
:local myarray {type="ford";model="mustang";color="green";year=2012}
:set $myarray ($myarray, "color=white")
:put $myarray
}
color=white;color=green;model=mustang;type=ford;year=2012
So is the car white or green?
Last edited by krisjanisj on Tue Aug 27, 2019 10:04 am, edited 1 time in total.
Reason: Leave one line free above and below [code][/code] block for it to properly work
 
pe1chl
Forum Guru
Forum Guru
Posts: 10234
Joined: Mon Jun 08, 2015 12:09 pm

Re: Array Push Function

Tue Aug 27, 2019 12:39 pm

My worry with solutions like this is normally "what is going on under the hood"...
Maybe it is my bad that I started programming 40 years ago and back then the beautiful solution often was too slow to be usable in practice. Of course that has changed a little today, although a lot of the slowness of modern systems can be explained by careless programming by people who do not know about efficiency.

A statement like: :set $MyArray ($MyArray, $Value); looks nice and easy, but I fear that it will copy the entire existing array everytime you add a single value to it.
That could end up disastrous when you have many values in the array.
 
Retral
newbie
Posts: 33
Joined: Wed Jul 25, 2018 9:10 pm

Re: Array Push Function

Wed Sep 30, 2020 8:59 pm

My worry with solutions like this is normally "what is going on under the hood"...
Maybe it is my bad that I started programming 40 years ago and back then the beautiful solution often was too slow to be usable in practice. Of course that has changed a little today, although a lot of the slowness of modern systems can be explained by careless programming by people who do not know about efficiency.

A statement like: :set $MyArray ($MyArray, $Value); looks nice and easy, but I fear that it will copy the entire existing array everytime you add a single value to it.
That could end up disastrous when you have many values in the array.
Thank you for your post. I will be sure to take that into consideration next time I'm programming.
 
User avatar
SiB
Forum Guru
Forum Guru
Posts: 1888
Joined: Sun Jan 06, 2013 11:19 pm
Location: Poland

Re: Array Push Function

Thu Oct 01, 2020 2:07 am

That thread is that good that I add some my own answer about Functions from past :) I hope they give some light to that post :).

#4 with #7 who have additional information and QUIZ :)

Who is online

Users browsing this forum: No registered users and 40 guests