cycle "for" in Python - python

I have to create a three new lists of items using two different lists.
list_one = ['one', 'two','three', 'four','five']
list_two = ['blue', 'green', 'white']
So, len(list_one) != len(list_two)
Now I should create an algorithm(a cycle) which can do this:
[oneblue, twoblue, threeblue, fourblue, fiveblue]. Same for 'green' and 'white'.
I undestand that I should create three cycles but I don't know how.
I've tried to make a function like this but it doesn't works.
def mix():
i = 0
for i in range(len(list_one)):
new_list = list_one[i]+list_two[0]
i = i+1
return new_list
What am I doing wrong?

I think you might be looking for itertools.product:
>>> [b + a for a,b in itertools.product(list_two, list_one)]
['oneblue',
'twoblue',
'threeblue',
'fourblue',
'fiveblue',
'onegreen',
'twogreen',
'threegreen',
'fourgreen',
'fivegreen',
'onewhite',
'twowhite',
'threewhite',
'fourwhite',
'fivewhite']

You should do this
def cycle(list_one,list_two):
newList = []
for el1 in list_two:
for el2 in list_one:
newList.append(el2+el1)
return newList

There are a few problems with your code:
When you do a for loop for i in ...:, you do not need to initialize i (i = 0) and you should not increment it (i = i + 1) since Python knows that i will take all values specified in the for loop definition.
If your code indentation (indentation is very important in Python) is truly the one written above, your return statement is inside the for loop. As soon as your function encounters your return statement, your function will exit and return what you specified: in this case, a string.
new_list is not a list but a string.
In Python, you can loop directly over the list items as opposed to their index (for item in list_one: as opposed to for i in range(len(list_one)):
Here is your code cleaned up:
def mix():
new_list = []
for i in list_one:
new_list.append(list_one[i]+list_two[0])
return new_list
This can be rewritten using a list comprehension:
def mix(list_one, list_two):
return [item+list_two[0] for item in list_one]
And because list_two has more than one item, you would need to iterate over list_two as well:
def mix(list_one, list_two):
return [item+item2 for item in list_one for item2 in list_two]

return should be out of for loop.
No need to initialize i and increment it, since you are using range.
Also, since both list can be of variable length, don't use range. Iterate over the list elements directly.
def mix(): should be like def mix(l_one,l_two):
All above in below code:
def mix(l_one,l_two):
new_list = []
for x in l_one:
for y in l_two:
new_list.append(x+y)
return new_list
list_one = ['one', 'two','three', 'four','five']
list_two = ['blue', 'green', 'white']
n_list = mix(list_one,list_two)
print n_list
Output:
C:\Users\dinesh_pundkar\Desktop>python c.py
['oneblue', 'onegreen', 'onewhite', 'twoblue', 'twogreen', 'twowhite', 'threeblu
e', 'threegreen', 'threewhite', 'fourblue', 'fourgreen', 'fourwhite', 'fiveblue'
, 'fivegreen', 'fivewhite']
C:\Users\dinesh_pundkar\Desktop>
Using List Comprehension, mix() function will look like below:
def mix(l_one,l_two):
new_list =[x+y for x in l_one for y in l_two]
return new_list

Related

Modify a list using an integer

I am trying to figure out the following:
I take as input a list of lists and an integer N and the objective is to repeat the elements of the sublists N times by adding in front of each element a number in the range of N in increasing order.
For example as input we would receive:
>>> conversion([['GREEN', 'PURPLE'], ['RED']], 3)
[['GREEN0', 'GREEN1', 'GREEN2', 'PURPLE0', 'PURPLE1', 'PURPLE2'], ['RED0', 'RED1', 'RED2']]
My idea was creating an empty list, then adding each element of each sublist in this empty list. Then I would replace the elements with the same version and add range(N) at the end of it but in writing the code I either cannot separate the elements of sublists in the new list or cannot add or separate the different copies of the elements and the values in range(N)
I hope my explanation was clear and thank you for any help possible.
Your idea of a new list is correct. Here is one possible solution.
def conversion(l, n):
new_list = []
for inner_list in l:
new_list.append([])
for word in inner_list:
for i in range(n):
new_list[-1].append(word + str(i))
return new_list
One-liner alternative. (Just for fun):
def conversion(l, n):
return [[word + str(i) for word in inner_list for i in range(n)] for inner_list in l ]
def conversion(input_list, count):
output_list = [
[
input_list[k][j] + str(i)
for j in range(len(input_list[k]))
for i in range(count)
]
for k in range(len(input_list))
]
return output_list
It may be useful to separate the two tasks into smaller functions to make it easier to understand. use listrepeater() to achieve the desired outcome of a list, and then run it in nestedListRepeater()
def listrepeater(l,multiplier):
output = []
for val in l:
for i in range(multiplier):
output.append(val + str(i))
i+=1
return output
def nestedListRepeater(inputlist,multiplier):
outputlist = []
for sublist in inputlist:
outputlist.append(listrepeater(sublist,multiplier))
return outputlist
nestedListRepeater([['GREEN', 'PURPLE'], ['RED']],3)

How to extend a list by overwriting the common values

list1=[{"status":1, "s_count":100}, {"status":2, "s_count":20}]
list2=[{"status":1, "s_count":0}, {"status":3, "s_count":30}]
list1.extend(list2) gives
[{"status":1, "s_count":100}, {"status":2, "s_count":20}, {"status":1,
"s_count":0}, {"status":3, "s_count":30}]
what I want is,
[{"status":1, "s_count":0}, {"status":2, "s_count":20}, {"status":3, "s_count":30}]
1) Consider using a dictionary instead of a list.
2) If you insist on using a list:
helper = []
for i in range(0,len(list1)):
for item in list2:
if item['status'] == list1[i]['status']:
list1[i]['s_count'] = item['s_count']
helper.add(item)
for item in helper:
list2.remove(item)
list1.extend(list2)
This is inefficient, so try to do 1 if possible.

Group elements of a list based on repetition of values

I am really new to Python and I am having a issue figuring out the problem below.
I have a list like:
my_list = ['testOne:100', 'testTwo:88', 'testThree:76', 'testOne:78', 'testTwo:88', 'testOne:73', 'testTwo:66', 'testThree:90']
And I want to group the elements based on the occurrence of elements that start with 'testOne'.
Expected Result:
new_list=[['testOne:100', 'testTwo:88', 'testThree:76'], ['testOne:78', 'testTwo:88'], ['testOne:73', 'testTwo:66', 'testThree:90']]
Just start a new list at every testOne.
>>> new_list = []
>>> for item in my_list:
if item.startswith('testOne:'):
new_list.append([])
new_list[-1].append(item)
>>> new_list
[['testOne:100', 'testTwo:88', 'testThree:76'], ['testOne:78', 'testTwo:88'], ['testOne:73', 'testTwo:66', 'testThree:90']]
Not a cool one-liner, but this works also with more general labels:
result = [[]]
seen = set()
for entry in my_list:
test, val = entry.split(":")
if test in seen:
result.append([entry])
seen = {test}
else:
result[-1].append(entry)
seen.add(test)
Here, we are keeping track of the test labels we've already seen in a set and starting a new list whenever we encounter a label we've already seen in the same list.
Alternatively, assuming the lists always start with testOne, you could just start a new list whenever the label is testOne:
result = []
for entry in my_list:
test, val = entry.split(":")
if test == "testOne":
result.append([entry])
else:
result[-1].append(entry)
It'd be nice to have an easy one liner, but I think it'd end up looking a bit too complicated if I tried that. Here's what I came up with:
# Create a list of the starting indices:
ind = [i for i, e in enumerate(my_list) if e.split(':')[0] == 'testOne']
# Create a list of slices using pairs of indices:
new_list = [my_list[i:j] for (i, j) in zip(ind, ind[1:] + [None])]
Not very sophisticated but it works:
my_list = ['testOne:100', 'testTwo:88', 'testThree:76', 'testOne:78', 'testTwo:88', 'testOne:73', 'testTwo:66', 'testThree:90']
splitting_word = 'testOne'
new_list = list()
partial_list = list()
for item in my_list:
if item.startswith(splitting_word) and partial_list:
new_list.append(partial_list)
partial_list = list()
partial_list.append(item)
new_list.append(partial_list)
joining the list into a string with delimiter |
step1="|".join(my_list)
splitting the listing based on 'testOne'
step2=step1.split("testOne")
appending "testOne" to the list elements to get the result
new_list=[[i for i in str('testOne'+i).split("|") if len(i)>0] for i in step2[1:]]

What should be the pythonic way to implement following logic?

I would like to loop a list and remove element if it meets the requirement. At the same time, I would transform the removed element and add the transformation result to another list.
Right now, I have implemented above logic by following code:
delete_set = set([])
for item in my_list:
if meet_requirement(item):
another_list.append = transform(item)
delete_set.add(item)
my_list = filter(lambda x:x not in delete_set, my_list)
The code is not so straight-forward, is there a better way to implement the logic?
You could do this with comprehensions only.
delete_set = set(I for I in my_list if meet_requirement(I))
another_list.extend(transform(I) for I in delete_set)
# or extend(transform(I) for I in my_list if I in delete_set), if duplicates/order matter
my_list = [I for I in my_list if I not in delete_set]
Not sure about pythonic, but if python had a partition function similar to haskell (or you could write a simple one yourself), the code wouldn't need to iterate over the original list twice (as in Cat Plus' solution).
I would use something like the following:
new_my_list, deleted_list = partition(my_list, meet_requirement)
deleted_list = [transform(e) for e in deleted_list]
you could do this
for i in reversed(xrange(len(my_list))):
if meet_requirement(my_list[i]):
another_list.append(transform(my_list.pop(i)))
then you might or might not want to reverse another_list (or you can use a deque and appendleft)
You could do this to avoid the set:
def part(items, others):
for item in items:
if meet_requirement(item):
others.append(item)
else:
yield item
mylist[:] = part(mylist, another_list)
>>> another_list = []
>>> new_list = []
>>>
>>> for item in my_list:
... (another_list if meet_requirement(item) else new_list).append(item)
...
>>> another_list = map(transform, another_list)
>>> my_list = new_list
zipped = zip(*[(item, transform(item)) for item in my_list \
if meet_requirement(item)])
another_list = zipped[1]
my_list = [item for item in my_list if item not in zipped[0]]
I needed something similar the other day:
def partition(pred, iterable):
result = ([], [])
for each in iterable:
result[pred(each)].append(each)
return result
xs = some_list
ys, xs[:] = partition(meet_some_requirement, xs)
ys = map(do_some_transformation, ys)
Or this one-pass variation:
def partition_and_transform(pred, iterable, *transform):
result = ([], [])
for each in iterable:
v = pred(each)
result[v].append(transform[v](each))
return result
ys, xs[:] = partition_and_transform(meet_some_reqirement, xs, do_some_transformation, lambda x:x)

Remove duplicates in a list while keeping its order (Python)

This is actually an extension of this question. The answers of that question did not keep the "order" of the list after removing duplicates. How to remove these duplicates in a list (python)
biglist =
[
{'title':'U2 Band','link':'u2.com'},
{'title':'Live Concert by U2','link':'u2.com'},
{'title':'ABC Station','link':'abc.com'}
]
In this case, the 2nd element should be removed because a previous "u2.com" element already exists. However, the order should be kept.
use set(), then re-sort using the index of the original list.
>>> mylist = ['c','a','a','b','a','b','c']
>>> sorted(set(mylist), key=lambda x: mylist.index(x))
['c', 'a', 'b']
My answer to your other question, which you completely ignored!, shows you're wrong in claiming that
The answers of that question did not
keep the "order"
my answer did keep order, and it clearly said it did. Here it is again, with added emphasis to see if you can just keep ignoring it...:
Probably the fastest approach, for a really big list, if you want to preserve the exact order of the items that remain, is the following...:
biglist = [
{'title':'U2 Band','link':'u2.com'},
{'title':'ABC Station','link':'abc.com'},
{'title':'Live Concert by U2','link':'u2.com'}
]
known_links = set()
newlist = []
for d in biglist:
link = d['link']
if link in known_links: continue
newlist.append(d)
known_links.add(link)
biglist[:] = newlist
Generators are great.
def unique( seq ):
seen = set()
for item in seq:
if item not in seen:
seen.add( item )
yield item
biglist[:] = unique( biglist )
This page discusses different methods and their speeds:
http://www.peterbe.com/plog/uniqifiers-benchmark
The recommended* method:
def f5(seq, idfun=None):
# order preserving
if idfun is None:
def idfun(x): return x
seen = {}
result = []
for item in seq:
marker = idfun(item)
# in old Python versions:
# if seen.has_key(marker)
# but in new ones:
if marker in seen: continue
seen[marker] = 1
result.append(item)
return result
f5(biglist,lambda x: x['link'])
*by that page
This is an elegant and compact way, with list comprehension (but not as efficient as with dictionary):
mylist = ['aaa','aba','aaa','aea','baa','aaa','aac','aaa',]
[ v for (i,v) in enumerate(mylist) if v not in mylist[0:i] ]
And in the context of the answer:
[ v for (i,v) in enumerate(biglist) if v['link'] not in map(lambda d: d['link'], biglist[0:i]) ]
dups = {}
newlist = []
for x in biglist:
if x['link'] not in dups:
newlist.append(x)
dups[x['link']] = None
print newlist
produces
[{'link': 'u2.com', 'title': 'U2 Band'}, {'link': 'abc.com', 'title': 'ABC Station'}]
Note that here I used a dictionary. This makes the test not in dups much more efficient than using a list.
Try this :
list = ['aaa','aba','aaa','aea','baa','aaa','aac','aaa',]
uniq = []
for i in list:
if i not in uniq:
uniq.append(i)
print list
print uniq
output will be :
['aaa', 'aba', 'aaa', 'aea', 'baa', 'aaa', 'aac', 'aaa']
['aaa', 'aba', 'aea', 'baa', 'aac']
A super easy way to do this is:
def uniq(a):
if len(a) == 0:
return []
else:
return [a[0]] + uniq([x for x in a if x != a[0]])
This is not the most efficient way, because:
it searches through the whole list for every element in the list, so it's O(n^2)
it's recursive so uses a stack depth equal to the length of the list
However, for simple uses (no more than a few hundred items, not performance critical) it is sufficient.
I think using a set should be pretty efficent.
seen_links = set()
for index in len(biglist):
link = biglist[index]['link']
if link in seen_links:
del(biglist[index])
seen_links.add(link)
I think this should come in at O(nlog(n))

Categories

Resources