Adding object to a list with a for loop? - python

I've done my research on stack overflow and could not find an answer that works out for me even though similar questions have been posted in the past. My issue is that I want to add string values that I am getting from a for loop that goes through a list and matches to a regular expression. I want to add them to a combined list of values, I am using a clean function that works on the submission of a form but when the data prints into my terminal it comes out like this:
['#example']
['#test']
when I want those values to print like this:
['#example', '#test',]
Here's my code in my views.py
def clean(self):
data = self.cleaned_data
regex = re.compile("\B#\w\w+")
tweeters = data['tweets']
split_tweets = tweeters.split()
for x in split_tweets:
if re.search(regex, x):
master_list = [x]
print master_list

You need to append to a list, otherwise you are just throwing away all the previous values
def clean(self):
data = self.cleaned_data
regex = re.compile("\B#\w\w+")
tweeters = data['tweets']
split_tweets = tweeters.split()
master_list = []
for x in split_tweets:
if re.search(regex, x):
master_list.append(x)
print master_list
You can also use a list comprehension here instead
def clean(self):
data = self.cleaned_data
regex = re.compile("\B#\w\w+")
tweeters = data['tweets']
split_tweets = tweeters.split()
master_list = [x for x in split_tweets if re.search(regex, x)]
print master_list

You're doing some strange things with that assignment. Why do you keep reassigning a list? Initialize the list before the loop, append() to it inside the loop, and print the whole thing after the loop.
master_list = []
for x in split_tweets:
if re.search(regex, x):
master_list.append(x)
print master_list

Do this instead:
def clean(self):
data = self.cleaned_data
regex = re.compile("\B#\w\w+")
tweeters = data['tweets']
split_tweets = tweeters.split()
master_list = []
for x in split_tweets:
if re.search(regex, x):
master_list.append(x)
print master_list
You need to append elements to the list instead of affecting a new "one element list" [x] to master_list, it get overridden by the next value

Related

Python how to create sublists in a loop

I have a python question about the following code block.
The expected output is a sublist, containing the name that is entered into the list, turn it into a gmail account and add a username that only shows the first 4 letters of the input. I currently have this code:
def database(L):
result = []
for i in L:
username = i[0:4]
result.append(i + '#gmail.com')
result.append(username)
return result
accounts = database(['Bakerfield', 'Thomas'])
print(accounts)
I currently get the output
['Bakerfield#gmail.com', 'Bake' , 'Thomas#gmail.com', 'Thom']
But I would like the output:
[['Bakerfield#gmail.com', 'Bake'], ['Thomas#gmail.com', 'Thom']]
This is because i am not using sublists, and I am unsure how to divide this function loop into one that creates a sublist out of these accounts and essentially seperates these lists.
Thanks in advance!!
Just do one append, but with a list:
def database(L):
result = []
for i in L:
username = i[0:4]
result.append([i + '#gmail.com', username])
return result
Output as required.
Your only issue is which the result.append section. Take a look at this revised code:
def database(L):
result = []
for i in L:
username = i[0:4]
result.append([i + '#gmail.com'])
result.append([username])
return result
accounts = database(['Bakerfield', 'Thomas'])
print(accounts)
Notice that you just forgot a single pair of brackets when using the append() function, this should fix it permanently.
I would use a dataclass for this. also, only one append required after instantiation.
from dataclasses import dataclass
#dataclass
class UsrEmial:
email: str
naem: str
def database(L):
result = []
for i in L:
username = i[0:4]
e_obj_for_usr = UsrEmial(f'{i}#gmail.com', username)
result.append(e_obj_for_usr)
# not do:
# result.append(username)
# reasoning: `UsrEmial` object contains already this info.
# here not do (2) appends, instead using only one (1) as above:
# result.append(i + '#gmail.com')
# result.append(username)
# reasoning: two appends will add to list but at the same level,
# such that 1st and 2nd append result will be as siblings with
# all the others in a list.
return result
accounts = database(['Bakerfield', 'Thomas'])
print(accounts)
# OK
assert accounts[-1].naem == 'Thomas'[0:4]
Out:
[UsrEmial(email='Bakerfield#gmail.com', naem='Bake'), UsrEmial(email='Thomas#gmail.com', naem='Thom')]

Store the output of a function into a variable

I have the following function that returns data:
def get_comments():
for i in data:
comment_data = i['comments']
for z in comment_data:
comments = comment_data['data']
for j in comments:
comment = j['message']
print(comment)
I would like to save the output of this function to a variable. I'm using print instead of return (in the function get_comments) since, return only returns the final row of my data. This is what i have tried to account for that:
def hypothetical(x):
return x
z = hypothetical(get_comments())
print(z)
However the output of the variable z is "None".
When i try some other value(i.e.):
z = hypothetical(5)
print(z)
z is equal to 5 of course.
Thanks
Instead of printing each line, you need to add it to a different data structure (such as a list) and return the whole list at the end of get_comments().
For example:
def get_comments():
to_return = []
for i in data:
comment_data = i['comments']
for z in comment_data:
comments = comment_data['data']
for j in comments:
comment = j['message']
to_return.append(comment)
return to_return
If you want to get a bit more advanced, you can instead create a generator using yield:
def get_comments():
for i in data:
comment_data = i['comments']
for z in comment_data:
comments = comment_data['data']
for j in comments:
comment = j['message']
yield comment
Then you can iterate over get_comments() and it will go back into the generator each time to get the next comment. Or you could simply cast the generator into a list with list(get_comments()) in order to get back to your desired list of comments.
Refer to this excellent answer for more about yield and generators.

How to concatenate output data coming out from for loop/function

I have a data set as a list. From that list I need to find a keyword, and if found, I should be able to extract the complete information of that element.
att =['Email/xyz#gmail.com', 'CountryCode/US','CountryCode/UK', 'ID/12345']
from the above list, if I search only CountryCode, then the output should come as:
['CountryCode/US','CountryCode/UK']
Below is my code which I am trying, but it is returning only a single value.
Can some one help me with this code, to return all of the values as :
['CountryCode/US','CountryCode/UK']
def att_func(field,data):
for i, j in enumerate(data):
# print(i,j)
if field in j:
return [data[i]]
att =['Email/xyz#gmail.com', 'CountryCode/US','CountryCode/UK', 'ID/12345']
field ='CountryCode'
Cntry = att_func('CountryCode',att)
print(Cntry)
You're returning early in your for loop so you'll never get past the first position where the field exists, you can either use yield instead of return and make your function return a generator or just use a list comprehension
def att_func(field, data):
return [i for i in data if field in i]
Reason : This is because you are returning as soon as single data is getting.
Solution : Collect all data in list and the return collected data.
Try:
def att_func(field,data):
final_data = []
for i, j in enumerate(data):
# print(i,j)
if field in j:
final_data.append(data[i])
return final_data
att =['Email/xyz#gmail.com', 'CountryCode/US','CountryCode/UK', 'ID/12345']
field ='CountryCode'
Cntry = att_func('CountryCode',att)
print(Cntry)
att = ['Email/xyz#gmail.com', 'CountryCode/US','CountryCode/UK', 'ID/12345']
out = [item for item in att if "CountryCode" in item]
Done !
Your att_func should look like this:
def att_func(needle, haystack):
return [item for item in haystack if needle in item]
More on list comprehensions.

Python: Functions and Lists?

I have a function that, when inputting a list and a specific string in that list, removes any duplicates of that specific string from the list. (find_start and find_end are separate functions that determine the first and last position of a certain string)
def remove_duplicates(sorted_list, item):
i = 0
real_list = []
for x in range(len(sorted_list)-1):
if(sorted_list[i] == item):
a = find_start(sorted_list, item)
b = find_end(sorted_list, item)
real_list = real_list + [item]
i = i+(b-a)
else:
real_list = real_list + [sorted_list[i]]
i+=1
return real_list
So for example, remove_duplicates(['a','a','b','b','c','c'], 'a') would return ['a','b','b','c','c']
I'm trying to define another function that uses this function in it for each iteration, like so
def remove_all_duplicates(sorted_list):
i = 0
list_tru = []
for x in range(len(sorted_list)):
list_tru = remove_duplicates(sorted_list, sorted_list[i])
i+=1
return list_tru
but if I input remove_all(['a','a','b','b','c','c']), it outputs ['a','a','b','b','c']. What am I doing wrong?
def remove_all_duplicates(L):
# NOTE: this modifies L IN-PLACE. Tread carefully
i = 1
while i<len(L):
if L[i] == L[i-1]:
del(L[i])
continue
i += 1
Usage:
In [88]: L = ['a','a','b','b','c','c']
In [89]: remove_all_duplicates(L)
In [90]: L
Out[90]: ['a', 'b', 'c']
With every iteration, you just keep going back to the original sorted_list. I would recommend copying it and then operating on that copy:
def remove_all_duplicates(sorted_list):
list_tru = sorted_list[:] # copy it
for x in set(sorted_list): # just use a set
list_tru = remove_duplicates(list_tru, x) # remove this character from your list
return list_tru
I've also turned the sorted list into a set so that you don't try to remove duplicates of the same letter multiple times, and removed the unnecessary i counter.
Of course, if all you really want to do is remove the duplicates from a sorted list of strings and you're not attached to the algorithm you're developing, that's particularly simple:
new_list = sorted(set(old_list))
def remove_duplicates(sorted_list):
for item in sorted_list:
hits = sorted_list.count(item)
while hits > 1:
sorted_list.remove(item)
hits = sorted_list.count(item)
return sorted_list
print(remove_duplicates(["a","a", "b", "b"]))
this is the simplest method I could come up with on the spot uses .count to tell if there are duplicates returns ["a", "b"]
You can use this too:
A = ['a','a','b','c','c'] #example of input list with duplicates
value = remove_duplicates(A) #pass the list to the function
print value #prints ['a','b','c']
def remove_duplicates(A):
B = [] #empty list
for item in A:
if item in B:
pass
else:
B.append(item) #Append the list
return B
Hope that this helps. Have a nice day.

add number to all elements of a list within a class?

so I have a class with a list, and I would like to add a number to all the elements of that list, but not to every list in the class. I tried this:
class class_name:
def __init__(self,list_name,other_list):
self.list_name = list_name
self.other_list = other_list
list1 = [1.0,2.0,3.0,4.0]
list2 = [4.0,5.0,6.0,7.0]
data = [0]*len(list1)
for i,(l1,l2) in enumerate(zip(list1,list2)):
data[i] = class_name(l1,l2)
[(x + 5.0).list_name for x in data]
and it gives me the error:
TypeError: unsupported operand type(s) for +: 'instance' and 'float'
edit: people seem to not understand what I want. In the real code I have, the lists have been added to a class (in this case data) which I've been working with, but one of the lists in the class (specifically referring to magnitudes) needs to be calibrated. I do this by adding a number to every element in that list to calibrate it. This has to be done to the list connected to the class it's in, so I can't edit the list before putting it into the class.
I already have this class created much earlier in my code, and I needed it to be the way it was before so that I could work with all the elements. Now, later in the code, I want to calibrate this magnitude list within the class. Is there a way to do that?
maybe this attempt better illustrates what I'm trying to do:
[x.list_name for x in data] = [x.list_name+5 for x in data]
this also doesn't work, I get this error:
SyntaxError: can't assign to list comprehension
I just feel like it makes people understand what I need.
Check out the Map function for python.
https://docs.python.org/2/tutorial/datastructures.html#functional-programming-tools
class class_name:
def __init__(self,list_name,other_list):
self.list_name = list_name
self.other_list = other_list
list1 = [1.0,2.0,3.0,4.0]
list2 = [4.0,5.0,6.0,7.0]
def add_five(x): return x+5
list1 = map(add_five, list1)
#or instead you can use a lambda
list1 = map(lambda x: x+5 , list1)
EDIT: maybe try this.
for class_name in class_names:
class_name.list_name = map(lambda x: x+5 , class_name.list_name)
If you want to increment one of two lists stored as a list of pairs, this should work:
[x.list_name+5.0 for x in class_names]
x isn't a number, it's the class_name object. You want to retrieve the thing you want to increment from x (x.list_name) and then add 5.0.
You are adding the value to the instance first then accessing the attribute.
class class_name:
def __init__(self,list_name,other_list):
self.list_name = list_name
self.other_list = other_list
list1 = [1.0,2.0,3.0,4.0]
list2 = [4.0,5.0,6.0,7.0]
class_names = [0]*len(list1)
for i,(l1,l2) in enumerate(zip(list1,list2)):
class_names[i] = class_name(l1,l2)
print [x.list_name+5.0 for x in class_names]
I am not sure what you mean, but I have created a simple example:
class class_name(object):
def __init__(self,list_name,other_list):
self.list_name = list_name
self.other_list = other_list
self.list1 = []
self.list2 = []
self.list1.append(self.list_name)
self.list2.append(self.other_list)
print "My List1: ", self.list1
print "My List2: ", self.list2
def input_data():
list_one = raw_input("Data for list 1: ")
list_two = raw_input("Data for list 2: ")
class_name(list_one, list_two)
if __name__ == '__main__':
input_data()
Is that what you want to?

Categories