python: repeating elements in a list based a predicateHow - python-2.7

I'd like to repeat elements of a list based on a predicate.
I tried using the module itertools and a list comprehension
abc = [1,2,3,4,5,6,7,8,9]
result = [ repeat(item,2) if item==3 or item==7 else item for item in abc ]
This doesn't fail at runtime, but the resulting object is not 'flattened'
If I print it, I see
[1, 2, repeat(3, 2), 4, 5, 6, repeat(7, 2), 8, 9]
Is it doable with a list comprehension?
Thanks

This works:
from itertools import repeat
abc = [1,2,3,4,5,6,7,8,9]
result = [x for y in (repeat(item,2) if item==3 or item==7 else [item] for item in abc)
for x in y]
>>> result
[1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9]
The trick here is to put item in its own list [item] and than flatten the now consistently nested list.
to improve readability, put it in two lines:
nested_items = (repeat(item,2) if item==3 or item==7 else [item] for item in abc)
result = [item for nested_item in nested_items for item in nested_item]
Since nested_items is an iterator, there is no extra list created her.

Related

Not able to flatten the list. need to understand how to flatten the list

I do not want to use any other built-in functions so just want to experiment the available list methods.
I am trying to flatten the list with the code below:
my_list = [1, 2, 3, 6, 4, [0, 8, 9]]
new_list = []
for num in my_list:
new_list.extend([num])
print(new_list)
Expecting an output like this: [1, 2, 3, 6, 4, 0, 8, 9]
Getting the following output: [1, 2, 3, 6, 4, [0, 8, 9]]
The extend function is used to append all the elements of an iterable to the existing list. But the above code isn't working.
You have a mixed array so you need to check for that. So a function like
def flatlist(l):
if l== []:
return []
elif type(l) is not list:
return [l]
else:
return flatlist(l[0]) + flatlist(l[1:])

Python - get repeat matches in two lists

I am trying to match two lists, but I want to pick up the repeat matches too. I can't use set because that would only give me {3} in my second example below.
a = [1,2,3,4]
b = [3,3,4,5]
return [3,4]
a = [1,2,3,3]
b = [3,3,4,5]
return [3,3]
You can use list comprehesion to check and return every item in a if it exists in b like below:
[item for item in a if item in b]
If you want only the elements that are in both a and b (to cover the cases mentioned by #kabanus in the comment), you can use the following:
[item for item in set(a) for i in range(min(a.count(item), b.count(item)))]
Output:
>>> a = [1, 2, 3, 4]
>>> b = [3, 3, 4, 5]
>>> [item for item in set(a) for i in range(min(a.count(item), b.count(item)))]
[3, 4]
>>>
>>> a = [1, 2, 3, 3]
>>> b = [3, 3, 4, 5]
>>> [item for item in set(a) for i in range(min(a.count(item), b.count(item)))]
[3, 3]
>>>
>>> a = [3, 3, 4]
>>> b = [4, 4, 3]
>>> [item for item in set(a) for i in range(min(a.count(item), b.count(item)))]
[3, 4]
Try something like (if order doesn't matter), Python 2:
from collections import Counter
a = [1,2,3,4]
b = [3,3,4,5]
ca=Counter(a)
cb=Counter(b)
print sum([[x]*min(ca[x],cb[x]) for x in set(a)],[])
This should return the list of all repeating matches the number of time they repeat, with no particular ordering beyond grouping together same elements. The output for the above example is:
[3,4]
I'm assuming you missed 4. The other example you have yields what you posted:
[3,3]

python3.2)append two element in a list(lists in a list)

If I have an input like this (1, 2, 3, 4, 5, 6)
The output has to be ... [[1, 2], [3, 4], [5, 6]].
I know how to deal with if it's one element but not two.
x=[]
for number in numbers:
x.append([number])
I'll appreciate your any help!
Something like this would work:
out = []
lst = (1,2,3,4,5,6,7,8,9,10)
for x in range(len(lst)):
if x % 2 == 0:
out.append([lst[x], lst[x+1]])
else:
continue
To use this, just set lst equal to whatever list of numbers you want. The final product is stored in out.
There is a shorter way of doing what you want:
result = []
L = (1,2,3,4,5,6,7,8,9,10)
result = [[L[i], L[i + 1]] for i in range(0, len(L) - 1, 2)]
print(result)
You can use something like this. This solution also works for list of odd length
def func(lst):
res = []
# Go through every 2nd value | 0, 2, 4, ...
for i in range(0, len(lst), 2):
# Append a slice of the list, + 2 to include the next value
res.append(lst[i : i + 2])
return res
# Output
>>> lst = [1, 2, 3, 4, 5, 6]
>>> func(lst)
[[1, 2], [3, 4], [5, 6]]
>>> lst2 = [1, 2, 3, 4, 5, 6, 7]
>>> func(lst2)
[[1, 2], [3, 4], [5, 6], [7]]
List comprehension solution
def func(lst):
return [lst[i:i+2] for i in range(0, len(lst), 2)]
Slicing is better in this case as you don't have to account for IndexError allowing it to work for odd length as well.
If you want you can also add another parameter to let you specify the desired number of inner elements.
def func(lst, size = 2): # default of 2 it none specified
return [lst[i:i+size] for i in range(0, len(lst), size)]
There's a few hurdles in this problem. You want to iterate through the list without going past the end of the list and you need to deal with the case that list has an odd length. Here's one solution that works:
def foo(lst):
result = [[x,y] for [x,y] in zip(lst[0::2], lst[1::2])]
return result
In case this seems convoluted, let's break the code down.
Index slicing:
lst[0::2] iterates through lst by starting at the 0th element and proceeds in increments of 2. Similarly lst[1::2] iterates through starting at the 1st element (colloquially the second element) and continues in increments of 2.
Example:
>>> lst = (1,2,3,4,5,6,7)
>>> print(lst[0::2])
(1,3,5,7)
>>> print(lst[1::2])
(2,4,6)
zip: zip() takes two lists (or any iterable object for that matter) and returns a list containing tuples. Example:
>>> lst1 = (10,20,30, 40)
>>> lst2 = (15,25,35)
>>> prit(zip(lst1, lst2))
[(10,15), (20,25), (30,35)]
Notice that zip(lst1, lst2) has the nice property that if one of it's arguments is longer than the other, zip() stops zipping whenever the shortest iterable is out of items.
List comprehension: python allows iteration quite generally. Consider the statement:
>>> [[x,y] for [x,y] in zip(lst1,lst2)]
The interior bit "for [x,y] in zip(lst1,lst2)" says "iterate through all pairs of values in zip, and give their values to x and y". In the rest of the statement
"[[x,y] for [x,y] ...]", it says "for each set of values x and y takes on, make a list [x,y] to be stored in a larger list". Once this statement executes, you have a list of lists, where the interior lists are all possible pairs for zip(lst1,lst2)
Very Clear solution:
l = (1, 2, 3, 4, 5, 6)
l = iter(l)
w = []
for i in l:
sub = []
sub.append(i)
sub.append(next(l))
w.append(sub)
print w

How do I add elements of a "zipped" list

I have a list and I want to add each of the pairs in the list
For example:
mylist = [(0,5), (4,5), (2,3)]
I want to get
newlist = [5, 9, 5]
Whatever language this is you could use a map. In python it would look like:
map(lambda x: x[0] + x[1], my_list)
Or even simpler:
map(sum, my_list)
Both returning:
[5, 9, 5]

Slicing a list into a list of sub-lists [duplicate]

This question already has answers here:
How do I split a list into equally-sized chunks?
(66 answers)
Closed 6 years ago.
What is the simplest and reasonably efficient way to slice a list into a list of the sliced sub-list sections for arbitrary length sub lists?
For example, if our source list is:
input = [1, 2, 3, 4, 5, 6, 7, 8, 9, ... ]
And our sub list length is 3 then we seek:
output = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ... ]
Likewise if our sub list length is 4 then we seek:
output = [ [1, 2, 3, 4], [5, 6, 7, 8], ... ]
[input[i:i+n] for i in range(0, len(input), n)] # Use xrange in py2k
where n is the length of a chunk.
Since you don't define what might happen to the final element of the new list when the number of elements in input is not divisible by n, I assumed that it's of no importance: with this you'll get last element equal 2 if n equal 7, for example.
The documentation of the itertools module contains the following recipe:
import itertools
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return itertools.izip_longest(fillvalue=fillvalue, *args)
This function returns an iterator of tuples of the desired length:
>>> list(grouper(2, [1,2,3,4,5,6,7]))
[(1, 2), (3, 4), (5, 6), (7, None)]
A really pythonic variant (python 3):
list(zip(*(iter([1,2,3,4,5,6,7,8,9]),)*3))
A list iterator is created and turned into a tuple with 3x the same iterator, then unpacked to zip and casted to list again. One value is pulled from each iterator by zip, but as there is just a single iterator object, the internal counter is increased globally for all three.
I like SilentGhost's solution.
My solution uses functional programming in python:
group = lambda t, n: zip(*[t[i::n] for i in range(n)])
group([1, 2, 3, 4], 2)
gives:
[(1, 2), (3, 4)]
This assumes that the input list size is divisible by the group size. If not, unpaired elements will not be included.