Random variable value with many random elements - xpath

I want to use a random value from the GET method, in the POST method.
List car = Audi, Porsche, Ford, VW, Honda, Citroen
$['carTypes'][0]['carType']['enum']
Result: [Audi]
$['carTypes'][${=(int)(Math.random()*6)}]['carType']['enum']
Result: [Porsche] (random 1 car from the list of 5 available)
I would like to get a list of random cars but not limited to just one car - random list of cars but in the range of 0 to 6, not only 1 value.
Result: [Audi,Porsche]
Result: [Ford, VW, Honda]
Result: [Citroen]
I have tried like this.
$['carTypes'][${=(int)(Math.random()*6)},${=(int)(Math.random()*6)}]['carType']['enum']
Result: [[Citroen, Honda]]
Probably 2 flat brackets [[ prevent me from using this data in the POST method, how to get rid of unnecessary brackets?
Groovy
import groovy.json.JsonOutput
Random random = new Random()
def list = ["Porsche","Ford","VW"]
def randomValue = random.nextInt(list.size())
def list2 = ["Porsche","Ford","VW"]
def randomValue2 = random.nextInt(list2.size())
def theValue = list2[randomValue2] +","+ list[randomValue]
I will be grateful for your help.

Instead of putting the above in your post step, you could create a Groovy script step in between the GET and POST requests.
In the Groovy script, you can then 'build' the string exactly how you want, including the removal of the brackets. The last line in the script should be a return statement that returns the string you built.
In the POST request, you can then 'pull' in the value from the groovy script step using the $ functionality. E.g. ${Groovy Script Name#result}

Related

I am not getting the desired output with my python code

<code>def CheckNumber(MyList, number):
counter=0
while number!=0:
for i,element in enumerate(MyList):
if number%10==element:
del MyList[i]
else:
continue
number = number/10
if len(MyList)==0:
return 1
else:
return 2
print("Program to print all the possible combinations of a number")
MyNumber = int(input("Enter the number: "))
MyList = []
while MyNumber!=0:
MyList.append(MyNumber%10)
MyNumber=int(MyNumber/10)
MyLimit = 10**(len(MyList)-1)
for i in range(MyLimit, MyLimit*10):
answer = CheckNumber(MyList, i)
if answer == 1:
print(i)
else:
continue`</code>
I am a beginner at programming and I was trying to write a code to print all the possible combinations of a number. If user enters a 3 digit number the program will check all the three digit numbers to find possible combinations but instead it gives all the numbers as output. For example if user enters 12 then the output should be 12 21 but instead it shows every number from 10 to 99.
As far as I know everything is working fine but the results are not as I expect.
This is a pass-by-reference vs pass-by-value problem. What that means is when you pass a list to a function in python you are not passing the values in that list, you are passing the list itself, or rather its location in memory. So when you are modifying MyList in your CheckNumber function you are actually modifying the MyList variable globally. This is not true for primitive types which is why modifying number does not change i in the for loop. Quick example:
def foo(my_list):
my_list.append('world')
print(my_list)
a = []
foo(a) # this will print out 'world'
print(a) # this will print out 'world'
b = 'hello'
foo(b.copy()) # This will print out 'hello world'
print(b) # Here we have not passed b directly into foo,
# but instead passed a copy, so this will just print out 'hello' as b
# has not been modified
To summarize variable are stored in a specific location in memory. When you pass-by-reference you are passing a long that location in memory so you variable will be mutated. If you pass-by-value, you function will create a new variable and store a copy of the data so you will not mutate your outer variable. In other languages you can specify which way to pass in a variable but afaik you cannot in python.
With that out of the way this is a very easy fix. You don't want to modify your original MyList so just make a copy of it and pass that into the function. You also forgot to cast number/10 to int in the CheckNumber function. The working code should look like this:
def CheckNumber(MyList, number):
counter=0
while number!=0:
for i,element in enumerate(MyList):
if number%10==element:
del MyList[i]
else:
continue
number = int(number/10)
if len(MyList)==0:
return 1
else:
return 2
print("Program to print all the possible combinations of a number")
MyNumber = int(input("Enter the number: "))
MyList = []
while MyNumber!=0:
MyList.append(MyNumber%10)
MyNumber=int(MyNumber/10)
MyLimit = 10**(len(MyList)-1)
for i in range(MyLimit, MyLimit*10):
answer = CheckNumber(MyList.copy(), i)
if answer == 1:
print(i)
else:
continue
More info on pass-by-reference:
What's the difference between passing by reference vs. passing by value?
https://blog.penjee.com/passing-by-value-vs-by-reference-java-graphical/
https://courses.washington.edu/css342/zander/css332/passby.html

multiprocessing a geopandas.overlay() throws no error but seemingly never completes

I'm trying to pass a geopandas.overlay() to multiprocessing to speed it up.
I have used custom functions and functools to partially fill function inputs and then pass the iterative component to the function to produce a series of dataframes that I then concat into one.
def taska(id, points, crs):
return make_break_points((vms_points[points.ID == id]).reset_index(drop=True), crs)
points_gdf = geodataframe of points with an id field
grid_gdf = geodataframe polygon grid
partialA = functools.partial(taska, points=points_gdf, crs=grid_gdf.crs)
partialA_results =[]
with Pool(cpu_count()-4) as pool:
for results in pool.map(partialA, list(points_gdf.ID.unique())):
partialA_results.append(results)
bpts_gdf = pd.concat(partialA_results)
In the example above I use the list of unique values to subset the df and pass it to a processor to perform the function and return the results. In the end all the results are combined using pd.concat.
When I apply the same approach to a list of dataframes created using numpy.array_split() the process starts with a number of processors, then they all close and everything hangs with no indication that work is being done or that it will ever exit.
def taskc(tracks, grid):
return gpd.overlay(tracks, grid, how='union').explode().reset_index(drop=True)
tracks_gdf = geodataframe of points with an id field
dfs = np.array_split(tracks_gdf, (cpu_count()-4))
grid_gdf = geodataframe polygon grid
partialC_results = []
partialC = functools.partial(taskc, grid=grid_gdf)
with Pool(cpu_count() - 4) as pool:
for results in pool.map(partialC, dfs):
partialC_results.append(results)
results_df = pd.concat(partialC_results)
I tried using with get_context('spawn').Pool(cpu_count() - 4) as pool: based on the information here https://pythonspeed.com/articles/python-multiprocessing/ with no change in behavior.
Additionally, if I simply run geopandas.overlay(tracks_gdf, grid_gdf) the process is successful and the script carries on to the end with expected results.
Why does the partial function approach work on a list of items but not a list of dataframes?
Is the numpy.array_split() not an iterable object like a list?
How can I pass a single df into geopandas.overlay() in chunks to utilize multiprocessing capabilities and get back a single dataframe or a series of dataframes to concat?
This is my work around but am also interested if there is a better way to perform this and similar tasks. Essentially, modified the partial function so the df split is moved to the partial function then I create a list of values from range() as my iteral.
def taskc(num, tracks, grid):
return gpd.overlay(np.array_split(tracks, cpu_count()-4)[num], grid, how='union').explode().reset_index(drop=True)
partialC = functools.partial(taskc, tracks=tracks_gdf, grid=grid_gdf)
dfrange = list(range(0, cpu_count() - 4))
partialC_results = []
with get_context('spawn').Pool(cpu_count() - 4) as pool:
for results in pool.map(partialC, dfrange):
partialC_results.append(results)
results_gdf = pd.concat(partialC_results)

Python: Printing vertically

The final code will print the distance between states. I'm trying to print the menu with the names of the states numbered and vertically. I really struggle to find my mistakes.
This code doesn't raise any error, it just prints nothing, empty.
state_data = """
LA 34.0522°N 118.2437°W
Florida 27.6648°N 81.5158°W
NY 40.7128°N 74.0060°W"""
states = []
import re
state_data1 = re.sub("[°N#°E]", "", state_data)
def process_states(string):
states_temp = string.split()
states = [(states_temp[x], float(states_temp[x + 1]), float(states_temp[x + 2])) for x in
range(0, len(states_temp), 3)]
return states
def menu():
for state_data in range(state_data1):
print(f'{state_data + 1} {name[number]}')
My first guess is, your code does not print anything without errors because you never actually execute process_airports() nor menu().
You have to call them like this at the end of your script:
something = process_airports(airport_data1)
menu()
This will now raise some errors though. So let's address them.
The menu() function will raise an error because neither name nor number are defined and because you are trying to apply the range function over a string (airport_data1) instead of an integer.
First fixing the range error: you mixed two ideas in your for-loop: iterating over the elements in your list airport_data1 and iterating over the indexes of the elements in the list.
You have to choose one (we'll see later that you can do both at once), in this example, I choose to iterate over the indexes of the list.
Then, since neither name nor number exists anywhere they will raise an error. You always need to declare variables somewhere, however, in this case they are not needed at all so let's just remove them:
def menu(data):
for i in range(len(data)):
print(f'{i + 1} {data[i]}')
processed_airports = process_airports(airport_data1)
menu(processed_airports)
Considering data is the output of process_airports()
Now for some general advices and improvements.
First, global variables.
Notice how you can access airport_data1 within the menu() function just fine, while it works this is not something recommended, it's usually better to explicitly pass variables as arguments.
Notice how in the function I proposed above, every single variable is declared in the function itself, there is no information coming from a higher scope. Again, this is not mandatory but makes the code way easier to work with and understand.
airport_data = """
Alexandroupoli 40.855869°N 25.956264°E
Athens 37.936389°N 23.947222°E
Chania 35.531667°N 24.149722°E
Chios 38.343056°N 26.140556°E
Corfu 39.601944°N 19.911667°E"""
airports = []
import re
airport_data1 = re.sub("[°N#°E]", "", airport_data)
def process_airports(string):
airports_temp = string.split()
airports = [(airports_temp[x], float(airports_temp[x + 1]), float(airports_temp[x + 2])) for x in
range(0, len(airports_temp), 3)]
return airports
def menu(data):
for i in range(len(data)):
print(f'{i + 1} {data[i]}')
# I'm adding the call to the functions for clarity
data = process_airports(airport_data1)
menu(data)
The printed menu now looks like that:
1 ('Alexandroupoli', 40.855869, 25.956264)
2 ('Athens', 37.936389, 23.947222)
3 ('Chania', 35.531667, 24.149722)
4 ('Chios', 38.343056, 26.140556)
5 ('Corfu', 39.601944, 19.911667)
Second and this is mostly fyi, but you can access both the index of a iterable and the element itself by looping over enumerate() meaning, the following function will print the exact same thing as the one with range(len(data)). This is handy if you need to work with both the element itself and it's index.
def menu(data):
for the_index, the_element in enumerate(data):
print(f'{the_index + 1} {the_element}')

Generate random values in JSR223 sampler in JMeter

def index = [];
def randoms = [];
def size = new File("C:/Users/320027671/Desktop/JmeterPerformanceSuit/CompleteSuit/STU3/Post/index.csv").readLines().size();
File file = new File("C:/Users/320027671/Desktop/JmeterPerformanceSuit/CompleteSuit/STU3/Post/index.csv");
file.each { line ->
index << line
randoms << __Random(0,size,)
}
The script is giving error
the method does not exists
the scirpt is working uptil index << line, the problem is with random function
I assume you use groovy as language (otherwise it won't work)
You can't use JMeter functions inside JSR223
You can randomize every line using for example RandomUtils:
org.apache.commons.lang3.RandomUtils.nextInt(0, size-1);
Your approach may fail to produce "random" numbers, especially on lesser file sizes you can get duplicate values in the randoms list so I would recommend doing something like:
1.upto(size, { i ->
randoms.add(i)
})
Collections.shuffle(randoms)
This will populate randoms list with the numbers from 1 to the length of size and then calls Collection.shuffle() function in order to "randomise" the list.
Just in case check out Writing JMeter Functions in Groovy for more insights.

Assigning values to different variable in JMeter

I have two different array with values as below:
Code = [8,9,10]
Value = [4,5,6]
I need to get the values from each array (above mentioned) randomly and assign it to different variable like below:
Code 1 = 9 , Code2=10
Value1 = 4 , Value2=6
Or is there any way in Jmeter to Pass that array to another sampler thereby assigning it to different variables.
How can we achieve it on Jmeter ? Any help / Suggestions is welcome!
Your values look utterly like JSON Arrays so my expectation is that you could handle it more easy using JSON Extractor
Just in case I'm wrong you can get random code and/or value using the following Groovy code in any of JSR223 Test Elements
import org.apache.commons.lang3.RandomUtils
def codes = vars.get('Code').findAll(/\d+/ )*.toInteger()
def values = vars.get('Value').findAll(/\d+/ )*.toInteger()
def randomCode = codes.get(RandomUtils.nextInt(0,codes.size()))
def randomValue = values.get(RandomUtils.nextInt(0,values.size()))
log.info('Random code: ' + randomCode)
log.info('Random value: ' + randomValue)
Demo:
You can use "Config Element" > "Random Variable" where you can give a range and ask for a random number within that given range.
Hope it helps.

Resources