I am having trouble with list comprehension in Python
Basically I have code that looks like this
output = []
for i, num in enumerate(test):
loss_ = do something
test_ = do something else
output.append(sum(loss_*test_)/float(sum(loss_)))
How can I write this using list comprehension such as:
[sum(loss_*test_)/float(sum(loss_))) for i, num in enumerate(test)]
however I don't know how to assign the values of loss_ and test_
You can use a nested list comprehension to define those values:
output = [sum(loss_*test_)/float(sum(loss_))
for loss_, test_ in ((do something, do something else)
for i, num in enumerate(test))]
Of course, whether that's any more readable is another question.
As Yaroslav mentioned in the comments, list comprehensions don't allow you to save a value into a variable directly.
However it allows you to use functions.
I've made a very basic example (because the sample you provided is incomplete to test), but it should show how you can still execute code in a list comprehension.
def loss():
print "loss"
return 1
def test():
print "test"
return 5
output = [loss()*test() for i in range(10) ]
print output
which is this case will result in a list [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
I hope this somehow shows how you could end up with the behaviour that you were looking for.
ip_list = string.split(" ") # split the string to a list using space seperator
for i in range(len(ip_list)): # len(ip_list) returns the number of items in the list - 4
# range(4) resolved to 0, 1, 2, 3
if (i % 2 == 0): ip_list[i] += "-" # if i is even number - concatenate hyphen to the current IP string
else: ip_list[i] += "," # otherwize concatenate comma
print("".join(ip_list)[:-1]) # "".join(ip_list) - join the list back to a string
# [:-1] trim the last character of the result (the extra comma)
Related
I have a small doubt , and i was not able to solve it , consider i have a list seperated with comma , and the data is dynamic may be 2 data or more than that
example : listVaue = ['Server1,Stop,Server2,START,.....,ServerN,StartN/StopN']
where N is a number
so if i have to split this into something like [[Server1,Stop],[Server2,Start2],....[ServerN,StartN/StopN]]
Is this possible . I wrote a code , but it is not working properly
listVaue = ['Server1,Stop,Server2,START']
c_index = listVaue.index("Stop")
l2 = listVaue[:c_index]
print(l2)
Can anyone help me solve this problem
This should work:
listValue = ["server1, stop, server2, start"]
listValue = listValue[0].split(",")
l2 = [[first_item, second_item] for first_item, second_item in zip(listValue[0::2], listValue[1::2])]
If you have a list defined as:
listVaue = ['Server1,Stop,Server2,START']
it actually only has one value, which is a string of value 'Server1,Stop,Server2,START'. If you can define a different list, I would suggest trying to do:
listVaue = ['Server1', 'Stop', 'Server2', 'START']
or even a list of tuples, if you would like values to be correspondent:
listVaue = [('Server1', 'Stop'), ('Server2', 'START')]
Now, if you don't have control over the input data (and therefore cannot change the original list), what you can do is to first split all values by comma and then aggregate them 2 by 2.
# Original list
listVaue = ['Server1,Stop,Server2,START']
# Split string into separate values
# Take the first element - from your code it looks
# like you only have a continuous string
new_list = listVaue[0].split(',')
# If you know that the list length will always be even, you can
# aggregate them 2 by 2 using the following code:
l2 = [(new_list[i], new_list.pop(i + 1)) for i in range(len(new_list) // 2)]
l2
>>> [('Server1', 'Stop'), ('Server2', 'START')]
What the code does is basically to get elements in position i and the next one as well (i + 1), removing the latter, whilst iterating through half the length of the list. Because you change its size as you iterate, always removing the second item, you'll end up only iterating through the original indexes 0, 2, 4, 6, 8..., whilst also retrieving their counterpart (1, 3, 5, 7, 9...).
Please note that changing the size of a list whilst you iterate is not generally a good practice, but because we are copying the original list, it shouldn't be a big problem for your case.
You can also change my code to whatever suits you, and you're probably better off with a normal for loop instead of a list comprehension:
listVaue = ['Server1,Stop,Server2,START']
new_list = listVaue[0].split(',')
l2 = []
for i in range(len(my_list) // 2):
# Change square brackets to round ones if you want a tuple (immutable) instead
l2.append([new_list[i], new_list.pop(i + 1)]
print(l2)
Try this:
listVaue = ['Server1,Command1,9182,Running,START,Server2,Command2,8888,Running,RESTART,ServerN,CommandN,N,Running,restart']
listVaue = listVaue[0].split(',')
a = ['START', 'RESTART', 'STOP', 'BOUNCE']
s = []
l2 = []
for i in listVaue:
s.append(i)
if i.upper() in a:
l2.append(s)
s = []
Why am I seeing this output while running this code:
list = []
for i in range(4):
l = int(input())
list.append(l)
print(str(list))
print("+".join(str(list)))
Output:
[1, 2, 3, 4]
[+1+,+ +2+,+ +3+,+ +4+]
Expected = [1+2+3+4]
Please correct my syntax
separator.join(sequence) inserts separator between each item in sequence; if sequence is a string, it simply sticks the separator in between every character of the string.
I think the root of your confusion is that you're converting the list into a string, when it seems like you really want to turn each item into a string (so that the list of strings can then be joined).
lst = [1, 2, 3, 4]
list_as_string = str(lst)
print(list_as_string)
=> "[1, 2, 3, 4]"
To make each item in the list a string, you can use a list comprehension. (List comprehensions are very useful Python tools for applying the same operation to each item in a sequence; if you haven't used them, check out this tutorial.)
list_of_strings = [str(i) for i in lst]
print(list_of_strings)
=> ["1", "2", "3", "4"]
The result of that can be joined like you would expect (and you can add brackets).
output = "[" + "+".join(list_of_strings) + "]"
print(output)
=> "[1+2+3+4]"
Alternatively, if for some reason you definitely want to convert the list to a string first, you can use the string.replace(old, new) method to simply replace every ", " with "+".
print(list_as_string.replace(", ", "+"))
=> "[1+2+3+4]"
Also note that list in Python is the actual name of the list class and it is a bad habit to redefine it as an ordinary variable.
You could use split(",") and "+".join().Also use .strip to remove the blank space.
Try this below:
print("+".join(map(str.strip, str(list).split(","))))
Result:
[1+2+3+4]
l = [1,2,3,4,5,'1','2','3','4','nag','nag','venkat',5,6,7]
l1 = []
for i in l:
if (str(i) not in l1) and (i not in l1):
l1.append(i)
print l1
I want to clean my list. My list contains numbers and strings. In the above list l i have both 1 and "1". I want to remove either 1 or "1". I want the output as [1, 2, 3, 4, 5, "nag", "venkat", 6, 7]
Confirmed in IDLE that this provides the output you're looking for. Also, I updated the names of some of your variables to be a little easier to understand.
my_list = [1,2,3,4,5,'1','2','3','4','nag','nag','venkat',5,6,7]
output_list = []
for i in my_list:
try:
if (str(i) not in output_list) and (int(i) not in output_list):
output_list.append(i)
except ValueError:
if i not in output_list:
output_list.append(i)
print output_list
In Python it's common practice to use variables assuming that they're a certain type and just catch errors, instead of going through the process of checking the type (int, str, etc) on each one. Here, inside the try statement, I'm assuming the loop variable i is either an int or a str that contains only numbers. Provided that's the case, this section works fine.
However, we know that the list contains some strings of letters, so the try block will throw a ValueError. The except block catches that and, knowing that this error will result from an attempt to cast a string of letters as an int (when we use int(i)), we can now safely assume that the loop variable i refers to a string of letters, which we then check against the output_list and append if needed. I hope that helps.
There's a way with list comprehensions, you create a new list, but this example only works if you know what you want to remove:
l1 = [i for i in l if i != "1" if i != "2" if i != "3" if i != "4"]
#output
[1, 2, 3, 4, 5, 'nag', 'nag', 'venkat', 5, 6, 7]
or for example only removing the string "1" it would be
l1 = [i for i in l if i != "1"]
Maybe it could be implemented in a function and a loop to remove such elements with a single if statement with this way. Not sure, anyway I'd go with coralv's way.
I have a python script that imports a CSV file and based on the file imported, I have a list of the indexes of the file.
I am trying to match the indexes in FILESTRUCT to the CSV file and then replace the data in the column with new generated data. Here is a code snip-it:
This is just a parsed CSV file returned from my fileParser method:
PARSED = fileParser()
This is a list of CSV column positions:
FILESTRUCT = [6,7,8,9,47]
This is the script that is in question:
def deID(PARSED, FILESTRUCT):
for item in PARSED:
for idx, lis in enumerate(item):
if idx == FILESTRUCT[0]:
lis = dataGen.firstName()
elif idx == FILESTRUCT[1]:
lis = dataGen.lastName()
elif idx == FILESTRUCT[2]:
lis = dataGen.email()
elif idx == FILESTRUCT[3]:
lis = dataGen.empid()
elif idx == FILESTRUCT[4]:
lis = dataGen.ssnGen()
else:
continue
return(PARSED)
I have verified that it is correctly matching the indices (idx) with the integers in FILESTRUCT by adding a print statement at the end of each if statement. That works perfectly.
The problem is that when I return(PARSED) it is not returning it with the new generated values, it is instead, returning the original PARSED input values. I assume that I am probably messing something up with how I use the enumerate method in my second loop, but I do not understand the enumerate method well enough to really know what I am messing up here.
You can use
item[idx] = dataGen.firstName()
to modify the underlying item. The reason here is that enumerate() returns (id, value) tuples rather than references to the iterable that you passed.
Given your example above you may not even need enumerate, because you're not parsing the lis at all. So you could also just do
for i in range(len(item)):
# your if .. elif statements go here ...
item[i] = dataGen.firstName()
On a side-note, the elif statements in your code will become unwieldy once you start adding more conditions and columns. Maybe consider making FILESTRUCT a dictionary like:
FILESTRUCT = {
6: dataGen.firstName,
7: dataGen.lastName,
....
}
...
for idx in range(len(item)):
if idx in FILESTRUCT.keys():
item[idx] = FILESTRUCT[idx]()
So PARSED is an iterable, and item is an element of it and is also an iterable, and you want to make changes to PARSED by changing elements of item.
So let's do a test.
a = [1, 2, 3]
print 'Before:'
print a
for i, e in enumerate(a):
e += 10
print 'After:'
print a
for e in a:
e += 10
print 'Again:'
print a
a[0] += 10
print 'Finally:'
print a
The results are:
Before:
[1, 2, 3]
After:
[1, 2, 3]
Again:
[1, 2, 3]
Finally:
[11, 2, 3]
And we see, a is not changed by changing the enumerated elements.
You aren't returning a changed variable. You don't ever change the variable FILESTRUCT. Rather make another variable, make it as you loop through FILESTRUCT and then return your new FILE.
You can't change the values in a loop like that, Kind of like expecting this to return all x's:
demo_data = "A string with some words"
for letter in demo_data:
letter = "x"
return demo_data
It won't, it will return: "A string with some words"
Hear me out, I do not simply want someone to solve this problem for me. I know it is not 100% complete yet, but currently when I run the program I get an error about "Can't convert 'list' object to str implicitly" I'm looking for help on how to fix this and why it is does this.
Here is the problem
Write code to print out each thing in the list of lists, L, with a '*' after it like
1*2*3*4*...8*a*b*c*d*
This requires knowing the print statement and using the end or sep argument option
Here is my list, sorry for not putting it in earlier
L = [[1,2,3,4],[5,6,7,8],['a','b','c','d']]
Here is my code at the moment
def ball(x): #random function name with one parameter
q = '' #
i = 0
if type(x) != list: #verifies input is a list
return"Error"
for i in x: #Looks at each variable in list
for j in i: #Goes into second layer of lists
q = q + j + '*'
print(q)
The reason for your error
"Can't convert 'list' object to str implicitly"
is that you're using the wrong variable in your nested for loops. Where you're concatenating values to your q variable, you mistakenly put q = q + i when you wanted q = q + j. You also will want to cast the value of j as a string so it can be concatenated with q. In order to get your desired output, you can simply add an asterisk into that statement - something like the following: q = q + str(j) + '*'. On a completely unrelated note, your else statement that just has "Mistake" in it should be removed completely - it doesn't follow an if and it doesn't actually return or assign to a variable.
Note that this is not the most elegant way to go about solving this problem. I agree with ilent2 that you should take a look at both list comprehension and the str.join() method.
If you have a list of strings,
myList = ['a', '123', 'another', 'and another']
You can join them using the str.join function:
Help on method_descriptor:
join(...)
S.join(iterable) -> string
Return a string which is the concatenation of the strings in the
iterable. The separator between elements is S.
myString = '#'.join(myList)
If your list contains mixed types or non-strings you need to convert each item to a string first:
anotherList = [1, 2, 'asdf', 'bwsg']
anotherString = '*'.join([str(s) for s in anotherList])
You might want to read about list comprehension or more about the join function. Note, the above doesn't print the output (unless you are using the interactive console), if you want the output to be printed you will need call print too
print myString
print anotherString
And, if you are working with lists-of-lists you may need to change how you convert each sub-list into a string (depending on your desired output):
myListList = [[1, 2, 3, 4], [2, 3, 6, 5], [6, 4, 3, 1]]
myOtherString = '#'.join(['*'.join([str(s) for s in a]) for a in myListList])
The last line is a little complicated to read, you might want to rewrite it as a nested for loop instead.