I defined a new variable
Name Value Description
categories (1, 2, 3, 4, 5) my categories ids
and in my path i want to get a random value from categories: category_id=my_random_value.
I even tried this
category_id=${__StringFromArrayAtRandomindex('1', '2', '3', '4', '5'}
but it doesn't work.
To obtain a random variable value from a list, first declare as User variables the list or available values, with a prefix and a incremental index:
country_1 Spain
country_2 France
country_3 Portugal
country_4 Italy
country_5 England
Then you can obtain a random value from the list concatenating the prefix with a random index in the interval:
${__V(country_${__Random(1,6,)})} --> "Spain", "France", "Portugal", etc...
Explanation
The __Random function will give you an index for your interval. To obtain values from 1 to 5, you have to call __Random(1,6,), as it will never reach the MAX value.
The __V function, will obtain the value of the variable with the given name.
${__Random(1,6,)} --> 1, 2, 3, 4, 5
country_${__Random(1,6,)} --> "country_1", "country_2", etc...
${__V(country_${__Random(1,6,)})} --> "Spain", "France", "Portugal", etc...
As example, to use the random variable as JSON body for a request, in Body Data:
}
"country":"${__V(country_${__Random(1,6,)})}"
}
For your scenario you could try to use the JSR233 components (Sampler, PreProcessor, PostProcessor) with a bit of java/groovy code.
E.g.:
Define your data as you've done:
Name Value
categories 1,2,3,4,5
(i.e. use comma as delimiter, no spaces before and after comma).
Use the JSR233 Sampler / PreProcessor / PostProcessor with the following code:
import java.util.Random;
String[] categories = (vars.get("categories")).split(",");
int idx = new Random().nextInt(categories.length);
String category = (categories[idx]);
vars.put("rnd_cat", category);
Refer to the randomly picked category using ${rnd_cat}.
__StringFromArrayAtRandomindex is not part of JMeter core nor part of JMeter plugins.
Is it a custom function ?
Furthermore, you have a syntax error (there is a missing ) at end:
${__StringFromArrayAtRandomindex('1', '2', '3', '4', '5')}
To do the same thing, use a CSV Data Set which will contain:
1
2
3
4
5
Set:
Variable Names=categoryId
You can then use it like this:
${categoryId}
Related
I have some source JSON files that contain {key:value} pairs, for example:
{firstName: "jason", lastName: "smith"}
I would like to take this JSON and create an array of key-value pairs as follows:
[{key: "firstName", value: "jason"},{key: "lastName", value: "smith"}]
I've seen the FROM_KEY_VALUE() function in the documentation, but what I want to do is the opposite of FROM_KEY_VALUE(). Do you have any ideas?
If the number of key value pairs are static, you can build two arrays, one of keys, and one of values. You can then ZIP_WITH_INDEX these arrays together to build your desired output. Using your example from the question. I've included some psuedo code below to show you how this works, in a real use case the keys_array[] and values_array[] would likely come from a staging table.
SELECT
ZIP_WITH_INDEX('key,value',keys_array[],values_array[]) as output_array
FROM staging_table
LET keys_array[] = ['firstName','lastName'],
values_array[] = ['jason','smith']
WHERE $commit_time BETWEEN RUN_START_TIME() and RUN_END_TIME();
The resulting array would be:
[{"index":0, "key":"firstName", "value":"jason"}
,{"index":1, "key":"lastName", "value":"smith"}]
If the fields in the two arrays are not static, you can use the ZIP function. The ZIP function will simply merge together any number of arrays, with automatically assigned field names.
SELECT
ZIP(keys_array[],values_array[]) as output_array
FROM staging_table
LET keys_array[] = ['firstName','lastName'],
values_array[] = ['jason','smith']
WHERE $commit_time BETWEEN RUN_START_TIME() and RUN_END_TIME();
The resulting array would look as follows:
[{"field0":"firstName","field1":"jason"}
,{"field0":"lastName","field1":"hall"}]
The field names could always be remapped if needed.
Here is a filter expression that successfully returns the value of 6 if the boolean parameter is set to true. However, I'm needing it to return both a 6 and a 3 if True.
=IIF(parameters!Maintenance.Value = Cbool("True"), 6, fields!Group_I.Value)
You can try something like this.
In your filter Expression, do something like this:
=Switch(Fields!Group_I.Value = 3, "Maintenance",
Fields!Group_I.Value = 6, "Maintenance",
True,"Other")
Use = for the Operator.
And use this for the Value expression:
=IIf(Parameters!Maintenance.Value = True, "Maintenance", "Other")
You may have to play around with the field names in the code above.
This will limit what is displayed in the table based on the value in the Fields!Group_I.Value. In the first expression you map the value to "Maintenance" if it is either 3 or 6, otherwise it goes to "Other". Then the second expression sets the filter values based on the parameter.
Hope this helps you out.
Hello I have a smarty variable which has values like (Number, Number, Number) and I would like to replace the middle part:
2, 3, 4, 5, 6 -> 2-6
1, 2, 3, 4 -> 1-4
7, 8, 9, 10, 11 -> 7-11
So basicaly I want to first and the last number to be combined by a "-" the rest should be removed. How can I achieve this in smarty?
Thanks in advance!
Smarty is a templating system. It's main purpose is to represent the data it receives from the PHP code (in variables) as HTML or any other text format.
The easiest way to do transformations like the one you need is to prepare them in the PHP code and assign them to variables.
On the other hand, such a transformation is not a business rule but a presentation detail; accordingly, it must be implemented in the view (Smarty) and not in the model (the PHP code).
The best solution for Smarty is to write a Smarty plugin (a modifier) that implements this transformation.
This is a simple example of how such a modifier could look like:
/**
* Smarty modifier plugin
*
* #param string|array $range input string or array
* #param string $separator the value to use as separator (e.g. '...')
* #return string
*/
function smarty_modifier_range($range, $separator = '-')
{
// If the input is a string (like "1,2,3,4"), convert it to an array
if (is_string($range)) {
$range = explode(',', $range);
} elseif (! is_array($range)) {
// If it's neither string, nor array then
// this modifier has no effect on it
return $range;
}
// A range must have at least two components
if (count($range) < 2) {
// It's not a range
return implode(',', $range);
}
// Use only the first and the last item
return reset($range).$separator.end($range);
}
In order to use it you have to tell Smarty where to find it. Create a directory for this plugin (maybe you will write more Smarty plugins) and put the function in a file named modifier.range.php in this directory.
Use the Smarty function addPluginsDir() during the initialization of your Smarty object to add this directory to the list of directories where it looks for plugins.
$smarty = new Smarty();
$smarty->addPluginsDir(array('... the path of the new director here'));
The modifier accepts arrays and strings that contain values separated by comma. It extracts from them the first and the last component (if there are at least two components) and return them joined by a configurable separator (default: -):
$smarty->assign('var1', range(12, 16));
$smarty->assign('var2', array(7, 8, 9, 10, 11));
$smarty->assign('var3', '2,3,4,5,6');
$smarty->assign('var4', '4');
$smarty->assign('var5', array(5, 10, 15));
$smarty->assign('var6', array(3, 5, 6, 4));
In templates:
{$var1|range} // 12-16 (modify array)
{$var2|range:".."} // 7..11 (use custom separator)
{$var3|range} // 2..5 (modify string)
{$var4|range} // 4 (there is no range here)
{$var5|range} // 5-15 (doesn't verify for gaps)
{$var6|range} // 3-4 (doesn't verify the order)
The last example shows a drawback of the plugin as it is exposed above. It doesn't verify if the values in the input array or string are sorted in the ascending order. Therefore, if they are not already sorted, its output is not quite correct.
However, this is a minor issue that can be easily solved using the sort PHP function.
Update: a more elaborate version of the plugin can be found on Github.
Are you sure that your variable is a string and not an array?
For an array: You could use foreach loop to process all array elements, but display only first and the last items.
Here is exactly what you need:
http://www.smarty.net/forums/viewtopic.php?p=3219
But for a string you could explode it on "," to get an array or regex_replace modifier:
http://www.smarty.net/docsv2/en/language.modifier.regex.replace.tpl
in java you can do this:
List<String> splitedList = Arrays.asList(variable.split(","));
String finalString=splitedList.get(0)+"-"+splitedList.get(splitedList.size()-1);
Instead of
key:
- thisvalue
- thatvalue
- anothervalue
I would like to have
key:
1. thisvalue
2. thatvalue
3. anothervalue
purely for human readability, with the same interpretation of {key: [thisvalue, thatvalue, anothervalue]}.
This doesn't seem to be part of the basic YAML syntax, but is there a way to achieve this - perhaps using some of the advanced arcanery that's possible in YAML?
(I realize that this can be approximated by writing the list as:
key:
- 1. thisvalue
- 2. thatvalue
- 3. anothervalue
but this is an ugly hack and I'd prefer a solution where the numbers had semantic purpose, rather than being just part of the value's text, that also requires being parsed and removed.)
There is no way to do that in YAML. You can however use a normal nesting of elements and then during parsing generate an array/list/dictionary based on those:
my_numbered_pseudo_list:
1: a
2: b
3: c
...
n: x
When you load the example from above you will get the dictionary with key "my_numbered_pseudo_list" and its value as a dictionary containing all nested pairs {"1" : "a", "2" : "b", ..., "n" : "x"}. Here is an example how it will look like:
import yaml
doc = '''
list:
1: a
2: b
3: c
4: d
'''
y = yaml.load(doc);
list = []
for i in y['list']:
list.append(y['list'].get(i))
print list
This will give you
['a', 'b', 'c', 'd']
If you want to make sure that the order is actually kept in the YAML file you have to do some sorting in order to get an ordered final list where the order described in the YAML file is kept.
I have also seen people use ordered hash calls on the resulting dictionary (here: "list") (such as in Ruby which I am not familiar with) so you might want to dig a little bit more.
IMPORTANT!
Read here and here. In short to make sure you get a really ordered list from your YAML you have to sort the dictionary you have as a pseudo-list by key and then extract the values and append those to your final list.
When using Python, in order to be able to preserve the key order in YAML mappings (and comments, anchor names etc), the mappings are read into special ordereddict derivatives if you use ruamel.yaml (diclaimer: I am the author) and the RoundTripLoader.
Those function as dicts transparently, but with that, and using the syntax proposed by rbaleksandar in her/his answer, you can just do:
import ruamel.yaml as yaml
yaml_str = """\
key:
1: thisvalue
2: thatvalue
3: anothervalue
4: abc
5: def
6: ghi
"""
data = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)
y = data['key']
print y.keys()[2:5]
print y.values()[2:5]
print y.items()[2:5]
to get:
[3, 4, 5]
['anothervalue', 'abc', 'def']
[(3, 'anothervalue'), (4, 'abc'), (5, 'def')]
without any special effort after loading the data.
The YAML specs state that the key ordering is not guaranteed, but in the YAML file they are of course ordered. If the parser doesn't throw this information awasy, things are much more useful e.g. for comparison between revisions of a file.
I am trying to set the bird group as two numbers so that when I assign a variable I can use multiple "else if" statements with that one group later on
Code:
Xcode doesn't let me do this I'm in Swift
Let birdgroup: UInt32 = 2, 3
You can use Array, Set, or a tuple to store multiple values in a single variable. If order matters, go with Array or tuple, but if the order doesn't matter, you can use Set. Array and Set both allow you to vary the number of values stored in your variable, while a tuple variable must always be the same length. Also, you can loop over the items in an array or set, but not over a tuple.
Array is the most often used of the three, so if you aren't sure which to use, it's a good first choice.
In summary, this table shows the possibilities and their properties:
Loopable Unloopable
Ordered Array Tuple
Unordered Set (none)
Finally, all the items in an array or set must be of the same type (or derived from the same type, if the array or set is defined with the base class). This is called homogeneous. A tuple can contain different types, also known as heterogeneous.
Homogeneous Heterogeneous
Ordered Array Tuple
Unordered Set (none)
Collection Types in the Swift documentation describes how to use Array and Set.
Array
Create an array with
var birdgroup: [UInt32] = [2, 3]
birdgroup[0] is equal to 2, and birdgroup[1] is equal to 3. You can also access the items by looping:
for bird in birdgroup {
println("\(bird)")
}
Set
You can declare a set with
var birdgroup: Set<UInt32> = [2, 3]
Because sets have no order (imagine every item is tossed together in a bag), you can't request the "first" or "second" item. Instead, loop over each item of the set:
for bird in birdgroup {
println("\(bird)")
}
Tuple
let birdgroup: (UInt32, UInt32) = (2, 3)
Tuples also retain the order of their items. birdgroup.0 is equal to 2, and birdgroup.1 to 3. You can also give each item of the tuple a name if you prefer that to a number:
let birdgroup: (UInt32, UInt32) = (foo: 2, bar: 3)
birdgroup.foo is 2, and birdgroup.bar is 3.
Additionally, the values in a tuple do not all need to be the same type. You can combine different types, such as
let heterogeneousTuple: (UInt32, String) = (2, "three")