Jmeter Groovy creating new list by iterting from previous list - groovy

I have a list (tsts) which is dynamic and derived in separation operation but can look like below.
I would like to iterate through tsts and create a new list --> list1, only picking up up to say up to index 2. I have tried the for loop and even--> tsts.eachWithIndex { item, index -> for some reason my list1 only contains the last item?
import org.apache.jmeter.util.JMeterUtils;
import groovy.json.JsonSlurper;
def jsonResponse = null;
List<String> tsts = new ArrayList<String>()
tsts = [10, 11, 12];
str1 = "abc"
def map1 = [:]
def list1 = []
int TCcntr = 2;
cnt1 = 0
System.out.println("1 My Loop begins----------------");
for(int i = 0;i<TCcntr;i++) {
map1.clear()
map1.put(str1,tsts[cnt1].toInteger());
System.out.println("map1----> "+map1);
// list1.add(map1);
list1 = list1+map1;
System.out.println("list---> "+list1);
cnt1 = cnt1+1;
}
My output
1 My Loop begins----------------
map1----> [abc:10]
list---> [[abc:10]]
map1----> [abc:11]
list---> [[abc:11], [abc:11]]
why does list 1 keep picking up the last item iteration? it should look like this
list1----> [[abc:10], [abc:11]]

This worked, Thanks to Dimitri and Tim, I also learned other methods
tsts = [10, 11, 12, 13];
str1 = "abc"
def list1 = []
int TCcntr = 3;
for(int i = 1;i<TCcntr;i++) {
map1 =[:]
map1.put(str1,tsts[i].toInteger());
list1 = list1+map1;
}
output
list---> [[abc:11], [abc:12]]

Related

Creating and Assigning values to a variable within a list

I want to create variables names to be assigned to each index in the values list. So Result0 = 10, Result1 = 3, Result2 = 44, Result1 = 56601. Trying to code a function that creates and assigns variables depending on the length of the values list. The Code below does not work.
Code:
values = [10,3,44,56601]
k= 0
for n in values:
Result{k} = n
k+=1
Expected Result
Result0 = 10
Result1 = 3
Result2 = 44
Result3 = 56601
As earlier posts, and #hulkinBrian pointed out similar case, this will be the approach: (credit to them all!)
dc = {}
for x in [10, 3, 44, 56601]:
dc['Result{0}'.format(x)] = x

Why is a list variable sometimes not impacted by changes in function as I thought python3 works on pass by reference with list variables?

For python3, I originally needed to extract odd and even positions from a list and assign it to new lists, then clear the original list. I thought lists were impacted by a function call through "pass by reference". Testing some scenarios, it works sometime. Could someone please explain how exactly python3 works here?
Case 1: empty list is populated with string as expected.
def func1(_in):
_in.append('abc')
mylist = list()
print(f"Before:\nmylist = {mylist}")
func1(mylist)
print(f"After:\nmylist = {mylist}")
Output case 1:
Before:
mylist = []
After:
mylist = ['abc']
Case 2: middle list element is replaced with string as expected.
def func2(_in):
_in[1] = 'abc'
mylist = list(range(3))
print(f"Before:\nmylist = {mylist}")
func2(mylist)
print(f"After:\nmylist = {mylist}")
Output case 2:
Before:
mylist = [0, 1, 2]
After:
mylist = [0, 'abc', 2]
Case 3: why is the list not empty after function call?
def func3(_in):
_in = list()
mylist = list(range(3))
print(f"Before:\nmylist = {mylist}")
func3(mylist)
print(f"After:\nmylist = {mylist}")
Output case 3:
Before:
mylist = [0, 1, 2]
After:
mylist = [0, 1, 2]
Case 4: working exactly as expected, but note I have returned all three lists from function.
def func4_with_ret(_src, _dest1, _dest2):
_dest1 = [val for val in _src[0:len(_src):2]]
_dest2 = [val for val in _src[1:len(_src):2]]
_src = list()
return _src, _dest1, _dest2
source = list(range(6))
evens, odds = list(), list()
print(f"Before function call:\nsource = {source}\nevens = {evens}\nodds = {odds}")
source, evens, odds = func4_with_ret(source, evens, odds)
print(f"\nAfter function call:\nsource = {source}\nevens = {evens}\nodds = {odds}")
Output case 4:
Before function call:
source = [0, 1, 2, 3, 4, 5]
evens = []
odds = []
After function call:
source = []
evens = [0, 2, 4]
odds = [1, 3, 5]
Case 5: why no impact on the variables outside the function if I do not explicitly return from function call?
def func5_no_ret(_src, _dest1, _dest2):
_dest1 = [val for val in _src[0:len(_src):2]]
_dest2 = [val for val in _src[1:len(_src):2]]
_src = list()
source = list(range(6))
evens, odds = list(), list()
print(f"Before function call:\nsource = {source}\nevens = {evens}\nodds = {odds}")
func5_no_ret(source, evens, odds)
print(f"\nAfter function call:\nsource = {source}\nevens = {evens}\nodds = {odds}")
Output case 5:
Before function call:
source = [0, 1, 2, 3, 4, 5]
evens = []
odds = []
After function call:
source = [0, 1, 2, 3, 4, 5]
evens = []
odds = []
Thank you.
Your ultimate problem is confusing (in-place) mutation with rebinding (also referred to somewhat less precisely as "reassignment").
In all the cases where the change isn't visible outside the function, you rebound the name inside the function. When you do:
name = val
it does not matter what used to be in name; it's rebound to val, and the reference to the old object is thrown away. When it's the last reference, this leads to the object being cleaned up; in your case, the argument used to alias an object also bound to a name in the caller, but after rebinding, that aliasing association is lost.
Aside for C/C++ folks: Rebinding is like assigning to a pointer variable, e.g. int *px = pfoo; (initial binding), followed later by px = pbar; (rebinding), where both pfoo and pbar are themselves pointers to int. When the px = pbar; assignment occurs, it doesn't matter that px used to point to the same thing as pfoo, it points to something new now, and following it up with *px = 1; (mutation, not rebinding) only affects whatever pbar points to, leaving the target of pfoo unchanged.
By contrast, mutation doesn't break aliasing associations, so:
name[1] = val
does rebind name[1] itself, but it doesn't rebind name; it continues to refer to the same object as before, it just mutates that object in place, leaving all aliasing intact (so all names aliasing the same object see the result of the change).
For your specific case, you could change the "broken" functions from rebinding to aliasing by changing to slice assignment/deletion or other forms of in-place mutation, e.g.:
def func3(_in):
# _in = list() BAD, rebinds
_in.clear() # Good, method mutates in place
del _in[:] # Good, equivalent to clear
_in[:] = list() # Acceptable; needlessly creates empty list, but closest to original
# code, and has same effect
def func5_no_ret(_src, _dest1, _dest2):
# BAD, all rebinding to new lists, not changing contents of original lists
#_dest1 = [val for val in _src[0:len(_src):2]]
#_dest2 = [val for val in _src[1:len(_src):2]]
#_src = list()
# Acceptable (you should just use multiple return values, not modify caller arguments)
# this isn't C where multiple returns are a PITA
_dest1[:] = _src[::2] # Removed slice components where defaults equivalent
_dest2[:] = _src[1::2] # and dropped pointless listcomp; if _src might not be a list
# list(_src[::2]) is still better than no-op listcomp
_src.clear()
# Best (though clearing _src is still weird)
retval = _src[::2], _src[1::2]
_src.clear()
return retval
# Perhaps overly clever to avoid named temporary:
try:
return _src[::2], _src[1::2]
finally:
_src.clear()

Turn a str into a reasonable list python beginner

I'm trying to separate a string into a list that make sense
for exampia, in order to count the items on the list.
for example: str - "tomatoes,eggs,milk"
and result: lst = ['tomatoes', 'eggs', 'milk']
the code I wrote was:
def separate_groceries(str):
lst = [1, 2, 3] # really limiting the len of str, i need it to be able to recive each str
p = 0
for i in str:
pos = str.find(',')
item = str[:pos]
lst[p] = (item)
p = p + 1
str = str[pos+1:]
return lst
str = "tomatoes,milk,eggs"
res = separate_groceries(str)
print(res)
thank you for your help!
Stimer,
Like Niranjan Nagaraju said, what you may only need is:
groceries_list = "tomatoes,milk,eggs"
res = groceries_list.split(',')
print(res)
You may find more information about the .split() string method in the official Python documentation.

Two lists - Append and exchange

I have this
def url = "http://myurl/".toURL().text
def root = new XmlSlurper().parseText(url)
def namn = root.data.'content-item'.'**'.findAll{ node-> node.name() == 'resourceURI' }*.text()
def mylist = []
namn.each{
mylist << it
}
println mylist
def namn2 = root.data.'content-item'.'**'.findAll{ node-> node.name() == 'relativePath' }*.text()
def mylist2 = []
namn2.each{
mylist2 << it
}
println mylist2
That will be the output of this:
[http://myurl/, http://myurl/]
[/Sixten/1.1.0.235/, /Sixten/1.1.0.331/]
I know want to Exchange it to be
[Sixten-1.1.0.235.nupkg, Sixten-1.1.0.331.nupkg]
and then appended to the first list so it would result like this
[http://myurl/Sixten-1.1.0.235.nupkg, http://myurl/Sixten-1.1.0.331.nupkg]
HOW?
You don't need to do the each to get the values into a list... You already have lists:
def myList = root.data.'content-item'
.'**'
.findAll{ node-> node.name() == 'resourceURI' }
*.text()
def myList2 = root.data.'content-item'
.'**'
.findAll{ node-> node.name() == 'relativePath' }
*.text()
Then, to manipulate myList2, you just need:
myList2 = myList2*.getAt(1..-2)*.replaceAll('/', '-')*.plus('.nupkg')
And to append the urls to the start just requires:
[myList,myList2].transpose().collect { a, b -> a + b }
How about this:
def myList = ['http://myurl/', 'http://myurl/']
def myList2 = ['/Sixten/1.1.0.235/', '/Sixten/1.1.0.331/']
myList2 = myList2.collect { list2Entry ->
list2Entry[1..-2].replaceAll('/', '-') + '.nupkg'
}
def lst = []
myList.eachWithIndex{ txt, idx ->
lst << txt + myList2[idx]
}
println lst
prints:
[http://myurl/Sixten-1.1.0.235.nupkg, http://myurl/Sixten-1.1.0.331.nupkg]
First, inside the collect the leading and trailing slashes are removed by removing the first and last char of the strings with [1..-2]. Then the slashes in the middle of the strings are replaced by minus with replaceAll and .nupkg is added with string concatenation.
Inside the eachWithIndex every string from myList is concatenated with the string inside myList2 at the same position and the resulting string is added to the newly created list lst.

Groovy pointer to list

As I'm totally new to Groovy I have this problem I don't know how to solve:
I wan't to get a new value from a list, which list is depending of the value of the input string:
Simplified Example:
class NewStringValue
{
def getValue (inpList)
{
def list1 = ["L1V1","L1V2","L1V3"];
def list2 = ["L2V1","L2V2","L2V3","L2V4"];
def worklist = Here is my problem, how do I get Worklist to point to the correct list according to the value in InpList, see calling ex. below?
def i = 0;
def j = worklist.size-1;
while (i<=j)
{
// some code.......
newValue = worklist[i];
}
return newValue;}
Example of calling above
value = getValue("list1")
You can use a map, and look up the values based on the key passed in:
class NewStringValue {
def getValue(inpList) {
def lookup = [
list1: ["L1V1","L1V2","L1V3"],
list2: ["L2V1","L2V2","L2V3","L2V4"]
]
def worklist = lookup[inpList]
def newValue = ''
worklist.each {
newValue += it
}
newValue
}
}
new NewStringValue().getValue('list2')

Resources