removing something from a list of tuples - python

Say I have a list:
[(12,34,1),(123,34,1),(21,23,1)]
I want to remove the 1 from each tuple in the list so it becomes
[(12,34),(123,34),(21,23)]

You want to truncate your tuples, use a list comprehension:
[t[:-1] for t in listoftuples]
or, as a simple demonstration:
>>> listoftuples = [(12,34,1),(123,34,1),(21,23,1)]
>>> [t[:-1] for t in listoftuples]
[(12, 34), (123, 34), (21, 23)]

Tuples are immutable, so you can not remove an item. However, you can create a new tuple from the old tuple not including the elements you do not want to. So, to delete an arbitrary item from each tuple from a list of tuples, you can do:
def deleteItem(lst, toDel):
return [tuple(x for x in y if x != toDel) for y in lst]
Result:
>>> lst = [(12,34,1),(123,34,1),(21,23,1)]
>>> deleteItem(lst, 1)
[(12, 34), (123, 34), (21, 23)]

>>> a=[(12, 34, 1), (123, 34, 1), (21, 23, 1)]
>>> [filter (lambda a: a != 1, x) for x in a]
[(12, 34), (123, 34), (21, 23)]
THis will remove all 1 from the tuple irrespective of index

Since you can't change tuples (as they are immutable), I suggest using a list of lists:
my_list = [[12,34,1],[123,34,1],[21,23,1]]
for i in my_list:
i.remove(1)
return my_list
This returns: [[12, 34], [123, 34], [21, 21]].

python 3.2
1. [(i,v)for i,v,c in list1]
2. list(map(lambda x:x[:2],list1))

Related

List comprehension not giving expected result

I have a list of tuples, with each tuple containing a tuple pair, coordinates.
list1 = [((11, 11), (12, 12)), ((21, 21), (22, 22)), ((31, 31), (32, 32))]
Using list comprehension I am trying to generate a list without them being paired but still in the same order.
I was able to get the result be looping and using .append() but I was trying to avoid this.
new_list = []
for i in list1:
for x in i:
new_list.append(x)
print(new_list)
this works and gives me the result I am looking for:
[(11, 11), (12, 12), (21, 21), (22, 22), (31, 31), (32, 32)]
But when I try list comprehension I get the last tuple pair repeated!
new_list = [x for x in i for i in list1]
print(new_list)
[(31, 31), (31, 31), (31, 31), (32, 32), (32, 32), (32, 32)]
I am sure it is a small thing I am doing wrong so would appreciate the help!!
try :
print([inner_tuple for outer_tuple in list1 for inner_tuple in outer_tuple])
Nested fors should come to the right side. for sub in list1 after that for x in sub.
And btw, you didn't get NameError: name 'i' is not defined because, you wrote that list-comprehension after the for loop. In that time i is a global variable and exists.
The execution of the loop is out-inner type
Your code misses is close but it takes x only
Your code:
new_list = []
for i in list1:
for x in i:
new_list.append(x)
which is equivalent to
new_list = [x for i in list1 for x in i]
So, now you can understand the variables how they are taking values from for loops

Slice array of tuples by its elements

For example, I have an array of tuples.
l=[(456,33,1),
(556,22,1),
(123,33,2),
(557,32,2),
(435,21,2)]
I want make the arrays of lists by the last element in each tuple, so that
l=[[(456,33),
(556,22)],
[(123,33),
(557,32),
(435,21)]]
How could I do that? Is there any elegant way?
l = [(456, 33, 1), (556, 22, 1), (123, 33, 2), (557, 32, 2), (435, 21, 2)]
out = {}
for v in l:
out.setdefault(v[-1], []).append(v[:-1])
out = list(out.values())
print(out)
Prints:
[[(456, 33), (556, 22)],
[(123, 33), (557, 32), (435, 21)]]
Another way of doing this would be with itertools.groupby.
from itertools import groupby
from operator import itemgetter
res = [[x[:-1] for x in g] for _, g in groupby(sorted(l, key=itemgetter(2)), itemgetter(2))]
which produces the desired:
[[(456, 33), (556, 22)], [(123, 33), (557, 32), (435, 21)]]
Note that if you can guarantee that the original list l is sorted by the 3rd item in the tuples, you can replace sorted(l, key=itemgetter(2)) with just l.
An alternative attempt is using this:
l=[(456,33,1),
(556,22,1),
(123,33,2),
(557,32,2),
(435,21,2)]
dict_ = {}
for v in l:
val1, val2, id_ = v
dict_[id_] = [[val1, val2]] if id_ not in dict_ else dict_[id_] + [[val1, val2]]
l = [dict_[x] for x in dict_]

Find duplicates in a list of lists with tuples

I am trying to find duplicates within tuples that are nested within a list. This whole construction is a list too. If there are other better ways to organize this to let my problem to be solved - I'd be glad to know, because this is something I build on the way.
pairsList = [
[1, (11, 12), (13, 14)], #list1
[2, (21, 22), (23, 24)], #list2
[3, (31, 32), (13, 14)], #list3
[4, (43, 44), (21, 22)], #list4
]
The first element in each list uniquely identifies each list.
From this object pairsList, I want to find out which lists have identical tuples. So I want to report that list1 has the same tuple as list3 (because both have (13,14). Likewise, list2 and list4 have the same tuple (both have (21,22)) and need to be reported. The position of tuples within the list doesn't matter (list2 and list4 both have (13,14) even though the position in the list the tuple has is different).
The output result could be anything iterable later on such as (1,3),(2,4) or [1,3],[2,4]. It is the pairs I am interested in.
I am aware of sets and have used them to delete duplicates within the lists in other situations, but cannot understand how to solve this problem. I can check like this if one list contains any element from the other list:
list1 = [1, (11, 12), (13, 14)]
list2 = [3, (31, 32), (13, 14)]
print not set(list1).isdisjoint(list2)
>>>True
So, the code below lets me know what lists have same tuple(s) as the first one. But what is the correct way to perform this on all the lists?
counter = 0
for pair in pairsList:
list0 = pairsList[0]
iterList = pairsList[counter]
if not set(list0).isdisjoint(iterList):
print iterList[0] #print list ID
counter += 1
The first element in each list uniquely identifies each list.
Great, then let's convert it to a dict first:
d = {x[0]: x[1:] for x in pairsList}
# d:
{1: [(11, 12), (13, 14)],
2: [(21, 22), (23, 24)],
3: [(31, 32), (13, 14)],
4: [(43, 44), (21, 22)]}
Let's index the whole data structure:
index = {}
for k, vv in d.iteritems():
for v in vv:
index.setdefault(v, []).append(k)
Now index is:
{(11, 12): [1],
(13, 14): [1, 3],
(21, 22): [2, 4],
(23, 24): [2],
(31, 32): [3],
(43, 44): [4]}
The output result could be anything iterable later on such as (1,3),(2,4) or [1,3],[2,4]. It is the pairs I am interested in.
pairs = [v for v in index.itervalues() if len(v) == 2]
returns [[1,3],[2,4]].

How to remove character from tuples in list?

How to remove "(" ,")" form
[('(10', '40)'), ('(40', '30)'), ('(20', '20)')]
by python?
Straightforward, use list comprehension and literal_eval.
>>> from ast import literal_eval
>>> tuple_list = [('(10', '40)'), ('(40', '30)'), ('(20', '20)')]
>>> [literal_eval(','.join(i)) for i in tuple_list]
[(10, 40), (40, 30), (20, 20)]
Depending on how you are currently storing the list:
def to_int(s):
s = ''.join(ch for ch in s if ch.isdigit())
return int(s)
lst = [('(10', '40)'), ('(40', '30)'), ('(20', '20)')]
lst = [(to_int(a), to_int(b)) for a,b in lst] # => [(10, 40), (40, 30), (20, 20)]
or
import ast
s = "[('(10', '40)'), ('(40', '30)'), ('(20', '20)')]"
s = s.replace("'(", "'").replace(")'", "'")
lst = ast.literal_eval(s) # => [('10', '40'), ('40', '30'), ('20', '20')]
lst = [(int(a), int(b)) for a,b in lst] # => [(10, 40), (40, 30), (20, 20)]
>>> L = [('(10', '40)'), ('(40', '30)'), ('(20', '20)')]
>>> [tuple((subl[0].lstrip("("), subl[1].rstrip(")"))) for subl in L]
[('10', '40'), ('40', '30'), ('20', '20')]
Or if you wan the numbers in your tuples to eventually be ints:
>>> [tuple((int(subl[0].lstrip("(")), int(subl[1].rstrip(")")))) for subl in L]
[(10, 40), (40, 30), (20, 20)]
You can call .strip('()') on individual items (if they are strings, like in your example) to strip trailing ( and ).
There are multiple ways to apply that on single elements:
list comprehension (most pythonic)
a = [tuple(x.strip('()') for x in y) for y in a]
map and lambda (interesting to see)
Python 3:
def cleanup(a: "list<tuple<str>>") -> "list<tuple<int>>":
return list(map(lambda y: tuple(map(lambda x: x.strip('()'), y)), a))
a = cleanup(a)
Python 2:
def cleanup(a):
return map(lambda y: tuple(map(lambda x: x.strip('()'), y)), a)
a = cleanup(a)
Process the original string instead. Let's call it a.
On a='((10 40), (40 30), (20 20), (30 10))' , you can call
[tuple(x[1:-1].split(' ')) for x in a[1:-1].split(', ')]
The [1:-1] trims brackets from the string, the splits split strings into lists of strings.
The for is a comprehension.
s = "((10 40), (40 30), (20 20), (30 10))"
print [[int(x) for x in inner.strip(' ()').split()] for inner in s.split(',')]
# or if you actually need tuples:
tuple([tuple([int(x) for x in inner.strip(' ()').split()]) for inner in s.split(',')])

check to see if lists contain same elements

I have a list
List1 = [(12,34),(12,6),(2,4),(1,3),(34,32),(34,6)]
and another list
List2 = [(12,34),(12,6),(2,4),(1,3),(34,32),(56,12),(78,23),(23,56)]
I want to create a new list, check the elements of the first against the elements of the second. Editing the second list basically. This list would become
List3 = [(56,12),(78,23),(23,56)]
If order/duplicates don't matter:
>>> A = [(12,34),(12,6),(2,4),(1,3),(34,32),(34,6)]
>>> B = [(12,34),(12,6),(2,4),(1,3),(34,32),(56,12),(78,23),(23,56)]
>>> set(B).difference(A)
set([(78, 23), (56, 12), (23, 56)])
Otherwise, if order does matter, just use a list comprehension check membership of a set (O(1) amortized membership checks):
>>> set_A = set(A)
>>> [x for x in B if x not in set_A]
[(56, 12), (78, 23), (23, 56)]
Keep in mind that this simple solution also works:
>>> [x for x in B if x not in A]
[(56, 12), (78, 23), (23, 56)]
It will just have to potentially scan through the entire list A every time it checks x not in A.

Categories