Python built-in list: remove one item - python

lst = [(32,(4,5)),(55,(5,6))]
Given a tuple (4,5), so I want to remove the first tuple in lst. How to do that?
Sorry, this wasn't clear, what I mean is remove the list item by the second item in each list item

lst2 = [(x, y) for (x, y) in lst if y != (4, 5)]
Removes ALL (4, 5) tuples, not just the first instance.

You could filter the list:
lst = filter(lambda x, y: y != (4,5), lst)

This removes the first list entry whose 2nd component matches, but don't use this to remove more than one. To do more than one use a list comp as others have suggested or iterate over a copy of the list (for eaxmple: for n in L[:]). Modifying a list that you are iterating has unexpected results.
>>> def remove(L,t):
... for n in L:
... if n[1]==t:
... L.remove(n)
... break
...
>>> L=[(1,(2,3)),(4,(5,6)),(7,(2,3))]
>>> remove(L,(2,3))
>>> L
[(4, (5, 6)), (7, (2, 3))]

Do you mean lst2 = [(a,) for (a,b) in lst]' ?
That will result in[(32,),(55,)]`

Related

Printing Tuple's items [duplicate]

I stumbled across the following code:
for i, a in enumerate(attributes):
labels.append(Label(root, text = a, justify = LEFT).grid(sticky = W))
e = Entry(root)
e.grid(column=1, row=i)
entries.append(e)
entries[i].insert(INSERT,"text to insert")
I don't understand the i, a bit, and searching for information on for didn't yield any useful results. When I try and experiment with the code I get the error:
ValueError: need more than 1 value to unpack
Does anyone know what it does, or a more specific term associated with it that I can google to learn more?
You could google "tuple unpacking". This can be used in various places in Python. The simplest is in assignment:
>>> x = (1,2)
>>> a, b = x
>>> a
1
>>> b
2
In a for-loop it works similarly. If each element of the iterable is a tuple, then you can specify two variables, and each element in the loop will be unpacked to the two.
>>> x = [(1,2), (3,4), (5,6)]
>>> for item in x:
... print "A tuple", item
A tuple (1, 2)
A tuple (3, 4)
A tuple (5, 6)
>>> for a, b in x:
... print "First", a, "then", b
First 1 then 2
First 3 then 4
First 5 then 6
The enumerate function creates an iterable of tuples, so it can be used this way.
Enumerate basically gives you an index to work with in the for loop. So:
for i,a in enumerate([4, 5, 6, 7]):
print(i, ": ", a)
Would print:
0: 4
1: 5
2: 6
3: 7
Take this code as an example:
elements = ['a', 'b', 'c', 'd', 'e']
index = 0
for element in elements:
print element, index
index += 1
You loop over the list and store an index variable as well. enumerate() does the same thing, but more concisely:
elements = ['a', 'b', 'c', 'd', 'e']
for index, element in enumerate(elements):
print element, index
The index, element notation is required because enumerate returns a tuple ((1, 'a'), (2, 'b'), ...) that is unpacked into two different variables.
[i for i in enumerate(['a','b','c'])]
Result:
[(0, 'a'), (1, 'b'), (2, 'c')]
You can combine the for index,value approach with direct unpacking of tuples using ( ). This is useful where you want to set up several related values in your loop that can be expressed without an intermediate tuple variable or dictionary, e.g.
users = [
('alice', 'alice#example.com', 'dog'),
('bob', 'bob#example.com', 'cat'),
('fred', 'fred#example.com', 'parrot'),
]
for index, (name, addr, pet) in enumerate(users):
print(index, name, addr, pet)
prints
0 alice alice#example.com dog
1 bob bob#example.com cat
2 fred fred#example.com parrot
The enumerate function returns a generator object which, at each iteration, yields a tuple containing the index of the element (i), numbered starting from 0 by default, coupled with the element itself (a), and the for loop conveniently allows you to access both fields of those generated tuples and assign variable names to them.
Short answer, unpacking tuples from a list in a for loop works.
enumerate() creates a tuple using the current index and the entire current item, such as (0, ('bob', 3))
I created some test code to demonstrate this:
list = [('bob', 3), ('alice', 0), ('john', 5), ('chris', 4), ('alex', 2)]
print("Displaying Enumerated List")
for name, num in enumerate(list):
print("{0}: {1}".format(name, num))
print("Display Normal Iteration though List")
for name, num in list:
print("{0}: {1}".format(name, num))
The simplicity of Tuple unpacking is probably one of my favourite things about Python :D
let's get it through with an example:
list = [chips, drinks, and, some, coding]
i = 0
while i < len(list):
if i % 2 != 0:
print(i)
i+=1
output:[drinks,some]
now using EMUNERATE fuction:(precise)
list = [chips, drinks, and, coding]
for index,items in enumerate(list):
print(index,":",items)
OUTPUT: 0:drinks
1:chips
2:drinks
3:and
4:coding

How to modify those tuples in a list of tuples that contain specific value by given index

I have a list of tuples, say
a = [('foo', 3), ('bar', 1)]
and I want to modify the second element in the tuple containing 'foo'. More specifically, I would like to increment that number. In other terms, I want to do
>>> increment(a, 'foo')
>>> print a
[('foo', 4), ('bar', 1)]
You can't directly change a value within a tuple (tuples are immutable). However, you can replace the element with a new tuple that looks very much like the old one:
def increment(a, name):
for i, x in enumerate(a):
if x[0] == name:
a[i] = (x[0], x[1] + 1)
break
As I mentioned in my comments, you can't change the contents of a tuple in this case, so to answer the question posed in title of your question (and replace the entire tuple at that index, if any, found):
a = [('foo', 3), ('bar', 1)]
def find_index(name, seq):
for i, tpl in enumerate(seq):
if tpl[0] == name:
return i
return None
i = find_index('foo', a)
if i is not None:
a[i] = a[i][0], a[i][1]+1
print(a)
Output:
[('foo', 4), ('bar', 1)]

How to get the index and occurance of each item using itertools.groupby()

Here's the story I have two lists:
list_one=[1,2,9,9,9,3,4,9,9,9,9,2]
list_two=["A","B","C","D","A","E","F","G","H","Word1","Word2"]
I want to find the indicies of consecutive 9's in list_one so that I can get corresponding string from list_two, I've tried:
group_list_one= [(k, sum(1 for i in g),pdn.index(k)) for k,g in groupby(list_one)]
I was hoping to get the index of the first 9 in each tuple and then try to go from there, but that did not work..
What can I do here??
P.S.: I've looked at the documentation of itertools but it seems very vague to me..
Thanks in advance
EDIT:
Expected output is (key,occurances,index_of_first_occurance)
something like
[(9, 3, 2), (9, 4, 7)]
Judging by your expected output, give this a try:
from itertools import groupby
list_one=[1,2,9,9,9,3,4,9,9,9,9,2]
list_two=["A","B","C","D","A","E","F","G","H","Word1","Word2"]
data = zip(list_one, list_two)
i = 0
out = []
for key, group in groupby(data, lambda x: x[0]):
number, word = next(group)
elems = len(list(group)) + 1
if number == 9 and elems > 1:
out.append((key, elems, i))
i += elems
print out
Output:
[(9, 3, 2), (9, 4, 7)]
But if you really wanted an output like this:
[(9, 3, 'C'), (9, 4, 'G')]
then look at this snippet:
from itertools import groupby
list_one=[1,2,9,9,9,3,4,9,9,9,9,2]
list_two=["A","B","C","D","A","E","F","G","H","Word1","Word2"]
data = zip(list_one, list_two)
out = []
for key, group in groupby(data, lambda x: x[0]):
number, word = next(group)
elems = len(list(group)) + 1
if number == 9 and elems > 1:
out.append((key, elems, word))
print out
Okay, I have oneliner solution. It is ugly, but bear with me.
Let's consider the problem. We have a list that we want to sum up using itertools.groupby.
groupby gives us a list of keys and iteration of their repetition. In this stage we can't calculate the index, but we can easily find the number of occurances.
[(key, len(list(it))) for (key, it) in itertools.groupby(list_one)]
Now, the real problem is that we want to calculate the indexes in relation to older data. In most oneliner common functions, we are only examining the current state. However, there is one function that let us take a glimpse at the past - reduce.
What reduce does, is to go over the iterator and execute a function with the last result of the function and the new item. For example reduce(lambda x,y: x*y, [2,3,4]) will calculate 2*3 = 6, and then 6*4=24 and return 24. In addition, you can choose another initial for x instead of the first item.
Let's use it here - for each item, the index will be the last index + the last number of occurences. In order to have a valid list, we'll use [(0,0,0)] as the initial value. (We get rid of it in the end).
reduce(lambda lst,item: lst + [(item[0], item[1], lst[-1][1] + lst[-1][-1])],
[(key, len(list(it))) for (key, it) in itertools.groupby(list_one)],
[(0,0,0)])[1:]
If we don't won't to add initial value, we can sum the numbers of occurrences that appeared so far.
reduce(lambda lst,item: lst + [(item[0], item[1], sum(map(lambda i: i[1], lst)))],
[(key, len(list(it))) for (key, it) in itertools.groupby(list_one)], [])
Of course it gives us all the numbers. If we want only the 9's, we can wrap the whole thing in filter:
filter(lambda item: item[0] == 9, ... )
Well, this may not be the most elegant solution, but here goes:
g = groupby(enumerate(list_one), lambda x:x[1])
l = [(x[0], list(x[1])) for x in g if x[0] == 9]
[(x[0], len(x[1]), x[1][0][0]) for x in l]
which gives
[(9, 3, 2), (9, 4, 7)]
This looks like a problem that would be too complicated to stick into a list comprehension.
element_index = 0 #the index in list_one of the first element in a group
for element, occurrences in itertools.groupby(list_one):
count = sum(1 for i in occurrences)
yield (element, count, element_index)
element_index += count
If you wanted to eliminate the element_index variable, think about what a cumulative_sum function would need to do, where it's value is dependent on all previous values that have been iterated.

python - iterating over a subset of a list of tuples

Lets say I have a list of tuples as follows
l = [(4,1), (5,1), (3,2), (7,1), (6,0)]
I would like to iterate over the items where the 2nd element in the tuple is 1?
I can do it using an if condition in the loop, but I was hoping there will a be amore pythonic way of doing it?
Thanks
You can use a list comprehension:
[ x for x in l if x[1] == 1 ]
You can iterate over tuples using generator syntax as well:
for tup in ( x for x in l if x[1] == 1 ):
...
How about
ones = [(x, y) for x, y in l if y == 1]
or
ones = filter(lambda x: x[1] == 1, l)
Just use the if. It's clear and simple.
for x, y in tuples:
if y == 1:
do_whatever_with(x)
Build a generator over it:
has_1 = (tup for tup in l if l[1] == 1)
for item in has_1:
pass
for e in filter(l, lambda x: x[1] == 1):
print e
Try this, using list comprehensions is the pythonic way to solve the problem:
lst = [(4,1), (5,1), (3,2), (7,1), (6,0)]
[(x, y) for x, y in lst if y == 1]
=> [(4, 1), (5, 1), (7, 1)]
Notice how we use tuple unpacking x, y to obtain each of the elements in the pair, and how the condition if y == 1 filters out only those element with value 1 in the second element of the pair. After that, you can do anything you want with the elements found, in particular, I'm reconstructing the original pair in this part at the left: (x, y)
Since you want to iterate, itertools.ifilter is a nice solution:
from itertools import ifilter
iter = ifilter(lambda x: x[1] == 1, l)
for item in iter:
pass

How are tuples unpacked in for loops?

I stumbled across the following code:
for i, a in enumerate(attributes):
labels.append(Label(root, text = a, justify = LEFT).grid(sticky = W))
e = Entry(root)
e.grid(column=1, row=i)
entries.append(e)
entries[i].insert(INSERT,"text to insert")
I don't understand the i, a bit, and searching for information on for didn't yield any useful results. When I try and experiment with the code I get the error:
ValueError: need more than 1 value to unpack
Does anyone know what it does, or a more specific term associated with it that I can google to learn more?
You could google "tuple unpacking". This can be used in various places in Python. The simplest is in assignment:
>>> x = (1,2)
>>> a, b = x
>>> a
1
>>> b
2
In a for-loop it works similarly. If each element of the iterable is a tuple, then you can specify two variables, and each element in the loop will be unpacked to the two.
>>> x = [(1,2), (3,4), (5,6)]
>>> for item in x:
... print "A tuple", item
A tuple (1, 2)
A tuple (3, 4)
A tuple (5, 6)
>>> for a, b in x:
... print "First", a, "then", b
First 1 then 2
First 3 then 4
First 5 then 6
The enumerate function creates an iterable of tuples, so it can be used this way.
Enumerate basically gives you an index to work with in the for loop. So:
for i,a in enumerate([4, 5, 6, 7]):
print(i, ": ", a)
Would print:
0: 4
1: 5
2: 6
3: 7
Take this code as an example:
elements = ['a', 'b', 'c', 'd', 'e']
index = 0
for element in elements:
print element, index
index += 1
You loop over the list and store an index variable as well. enumerate() does the same thing, but more concisely:
elements = ['a', 'b', 'c', 'd', 'e']
for index, element in enumerate(elements):
print element, index
The index, element notation is required because enumerate returns a tuple ((1, 'a'), (2, 'b'), ...) that is unpacked into two different variables.
[i for i in enumerate(['a','b','c'])]
Result:
[(0, 'a'), (1, 'b'), (2, 'c')]
You can combine the for index,value approach with direct unpacking of tuples using ( ). This is useful where you want to set up several related values in your loop that can be expressed without an intermediate tuple variable or dictionary, e.g.
users = [
('alice', 'alice#example.com', 'dog'),
('bob', 'bob#example.com', 'cat'),
('fred', 'fred#example.com', 'parrot'),
]
for index, (name, addr, pet) in enumerate(users):
print(index, name, addr, pet)
prints
0 alice alice#example.com dog
1 bob bob#example.com cat
2 fred fred#example.com parrot
The enumerate function returns a generator object which, at each iteration, yields a tuple containing the index of the element (i), numbered starting from 0 by default, coupled with the element itself (a), and the for loop conveniently allows you to access both fields of those generated tuples and assign variable names to them.
Short answer, unpacking tuples from a list in a for loop works.
enumerate() creates a tuple using the current index and the entire current item, such as (0, ('bob', 3))
I created some test code to demonstrate this:
list = [('bob', 3), ('alice', 0), ('john', 5), ('chris', 4), ('alex', 2)]
print("Displaying Enumerated List")
for name, num in enumerate(list):
print("{0}: {1}".format(name, num))
print("Display Normal Iteration though List")
for name, num in list:
print("{0}: {1}".format(name, num))
The simplicity of Tuple unpacking is probably one of my favourite things about Python :D
let's get it through with an example:
list = [chips, drinks, and, some, coding]
i = 0
while i < len(list):
if i % 2 != 0:
print(i)
i+=1
output:[drinks,some]
now using EMUNERATE fuction:(precise)
list = [chips, drinks, and, coding]
for index,items in enumerate(list):
print(index,":",items)
OUTPUT: 0:drinks
1:chips
2:drinks
3:and
4:coding

Categories