I have an issue rearding the passing of more than one array parameter. I was able to do a "for each" cycle to execute my array parameter "SPPATH", but unfortunately I can pass only one, here is my code:
{"SPPATH":"#{item()}","SPFOLPATH":"#{pipeline().parameters.SPFOLPATH}","updsppath":"#{pipeline().parameters.updsppath}","Storageacct":"#{pipeline().parameters.Storageacct}","sapath":"#{pipeline().parameters.sapath}","saoppath":"#{pipeline().parameters.saoppath}"}
I want to pass "updsppath" also in the array because my output is on different locations, is it possible to do that, if so, how?
thanks in advance
I have reproduced the above and able to iterate multiple arrays inside ForEach.
For this the length of the all arrays should be same.
Use another array for indexes of these.
For Sample I have two array parameters like below.
I have created another array for index like below.
#range(0,length(pipeline().parameters.arr1))
Give this index_array to ForEach.
Create a res array variable in pipeline and inside ForEach, use append variable with the below dynamic content.
#json(concat('{"arr1":"',pipeline().parameters.arr1[item()],'","SPFOLPATH":"',pipeline().parameters.arr2[item()],'"}'))
After ForEach if you look at variable result (for showing here I have assigned to another variable), it will give you the desired JSON.
Result:
You can use this procedure to generate the desired array of objects and pass it to the logic apps as per your requirement.
Related
Suppose I have a foreach inside of a pipe:
I'd like to iterate through the following:
#split(split(item().name,'_')[4],'-')[1]
However, I'd like to pass this formula in through a parameter.
I've defined a parameter myExpression with the desired value in the pipeline, and attempting to reference it like so:
Note that the full expression would be: {#pipeline().parameters.myExpression}
However, data factory does not execute that expression, rather it just accepts it as a verbatim string:
{#pipeline().parameters.myExpression}
How do we pass in an expression from parameters from within the pipeline?
When you define a parameter like this and pass the value, what you are doing is is send a string input, as the textbox doesn't accept expression. The only way to pass expression to a parameter is to pass it from another pipeline. Another issue we have is one ADF limitation - there can not be nested iterations. Calling a second pipeline solves both the issues.
Split your flow in two pipelines.
First (parent) pipeline - Keep all steps up until generating the array over which iteration has to happen.
#split(split(item().name,'_')[4],'-')[1]
Then, inside a for each loop, invoke an "Execute pipeline" activity. In there, pass the expression that you desire in a similar fashion-
In the child pipeline, define a string parameter to absorb the passed value. Then, use #pipeline().parameters.ParamName to use it in there.
HTH
your description lacks a lot of context of what are you trying to do. I can only presume that you generate array in one pipeline and you want to iterate it in another. Looking at your print screen it looks like you typed in your value, therefore output is a plain text. you should hit dynamic context
so it would look like this:
When I run Get-ChildItem in a directory with only one file, I get a single DirectoryInfo object:
PS H:\> (ls).GetType().Name
DirectoryInfo
As soon as I add a second file, the output becomes an array:
PS H:\> (ls).GetType().Name
Object[]
How should I deal with this dichotomy in a function? Ideally, I'd like to force it to return an Array even when there's only one element, preferably without having to put in conditional logic based on the result of GetType() or Length or whatever.
Use array operator #(): $Array=#(ls). That operator guaranteed that you will have an array even if pipeline return zero or one object.
Expanding on PetSerAl's answer, you could also cast the type you need more explicitly:
[array](ls) will get you a System.Array object with a single member, so you could use this in a place where you want to avoid creating a new variable but need a specific type
You can also specify arrays that contain only specific types by casting: [int[]]$integersOnly = 1,2,3 will give you a System.Array object that can only hold objects of type [int]
Keep in mind you can use .Net classes - what if you want an array you can modify easily? [System.Collections.ArrayList](ls) does that, enjoy using the Remove() method
A few other hints, while I'm at it:
Want to see what you can do with an object of a specific type? Pipe it to Get-Member, the single most useful command I can think of; it'll show you everything you can do with the object
Curious about a class and what it can do, or looking for details like the different constructors that are available? Just enter [<class_name_here>] and if the assembly is loaded it'll show you everything you want to know
I have variables with incremented numbers within, such as row0text, row1text, row2text, etc.
I've figured out how to dynamically create string versions of those variable names, but once I have those strings, how can I use them as actual variable names rather than strings in my code?
Example:
var row3text = "This is the value I need!"
var firstPart = "row"
var rowNumber = 3
var secondPart = "text"
var together = (firstPart+String(rowNumber)+secondPart)
// the below gives me the concatenated string of the three variables, but I'm looking for a way to have it return the value set at the top.
println (together)
Once I know how to do this, I'll be able to iterate through those variables using a for loop; it's just that at the moment I'm unsure of how to use that string as a variable name in my code.
Thanks!
Short Answer: There is no way to do this for good reason. Use arrays instead.
Long Answer:
Essentially you are looking for a way to define an unknown number of variables that are all linked together by their common format. You are looking to define an ordered set of elements of variable length. Why not just use an array?
Arrays are containers that allow you to store an ordered set or list of elements and access them by their ordered location, which is exactly what you're trying to do. See Apple's Swift Array Tutorial for further reading.
The advantage of arrays is that they are faster, far more convenient for larger sets of elements (and probably the same for smaller sets as well), and they come packaged with a ton of useful functionality. If you haven't worked with arrays before it is a bit of a learning curve but absolutely worth it.
This is how the structure is set up:
ClimateSubtractStruct = struct('net',NetClimatologySubtracted,'SW',SWClimatologySubtracted,'LW',LWClimatologySubtracted,'SWCF',SWCFClimatologySubtracted,'LWCF',LWCFClimatologySubtracted,'netclear',netclearClimatologySubtracted,'LWclear',LWclearClimatologySubtracted,'SWclear',SWclearClimatologySubtracted,'Clouds',TotalCloudForcingClimatologySubtracted, 'Precip',PrecipClimatologySubtracted);
fields = fieldnames(ClimateSubtractStruct);
Then I call GlobalCorrMap (which uses the inputnames as arguments for the title and filename of the plot). I then intend to use a for loop to run GlobalCorrMap to compare and plot correlations between each of these variables in the structure. An example argument is below:
GlobalCorrMap(ClimateSubtractStruct.(fields{1}),ClimateSubtractStruct.(fields{3}))
I'm wondering - is it possible for inputname to get the variable name of the variable that's called within structure? Or is it better for me to simply just rename the function so that it can take in the names of the two variables as two separate arguments?
I've got a list of files in an array. I want to enumerate those files, and remove specific files from it. Obviously I can't remove items from an array, so I want to use an ArrayList.
But the following doesn't work for me:
$temp = Get-ResourceFiles
$resourceFiles = New-Object System.Collections.ArrayList($temp)
Where $temp is an Array.
How can I achieve that?
I can't get that constructor to work either. This however seems to work:
# $temp = Get-ResourceFiles
$resourceFiles = New-Object System.Collections.ArrayList($null)
$resourceFiles.AddRange($temp)
You can also pass an integer in the constructor to set an initial capacity.
What do you mean when you say you want to enumerate the files? Why can't you just filter the wanted values into a fresh array?
Edit:
It seems that you can use the array constructor like this:
$resourceFiles = New-Object System.Collections.ArrayList(,$someArray)
Note the comma. I believe what is happening is that when you call a .NET method, you always pass parameters as an array. PowerShell unpacks that array and passes it to the method as separate parameters. In this case, we don't want PowerShell to unpack the array; we want to pass the array as a single unit. Now, the comma operator creates arrays. So PowerShell unpacks the array, then we create the array again with the comma operator. I think that is what is going on.
Probably the shortest version:
[System.Collections.ArrayList]$someArray
It is also faster because it does not call relatively expensive New-Object.