It may be the fact I haven't slept yet, but I can't find the solution to this problem, so I come to you all. I have a list, with a series of sub-lists, each containing two values, like so:
list = (
(2, 5),
(-1, 4),
( 7, -3)
)
I also have a variable, a similar list with two values, that is as such:
var = (0, 0)
I want to add all the x values in list, then all the y values, and then store the sums in var, so the desired value of var is:
var = (8, 6)
How could I do it? I apologize if the answer is something stupid simple, I just need to get this done before I can sleep.
sumvar = map(sum,zip(*my_list))
should do what you want i think
This sounds like a job for "reduce" to me:
reduce(lambda a,b: (a[0]+b[0],a[1]+b[1]), list)
(8,6)
you could also use another list comprehension method, (a bit more readable):
sum(a for a,b in tpl), sum(b for a,b in tpl)
(8,6)
Related
How to add value to tuple within list
a = [[('one','1'),('two','2')],[('three','3')]]
b = [['I','II'],['III']]
I want it to turn out like
a = [[('one','1','I'),('two','2','II')],[('three','3','III')]]
I try to use append but it doesn't work
Thanks for any help.
Tuples are immutable, which means you can't change them once they've been made. See here: https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences.
The only way to achieve what you want would be to either remake your list, or delete the elements and add the new versions in-place.
You could try something like this:
a = [(1, 'one'), (2, 'two'), (3, 'three')]
b = ["I", "II", "III"]
updated_a = [(*i, j) for i, j in zip(a, b)]
Where I've assumed you've typoed in your question, and that the list of numerals has this form instead.
Edit: Solved
I've solved this by creating dictionaries a and b where the keys are the tuples (x,y) and my values are the integers t. I then return my keys as sets, take the built-in intersection, then get the values for all intersecting (x,y) points.
a{(x,y): t, ...}
b{(x,y): t, ...}
c = set([*a]).intersection(set([*b]))
for each in c:
val_a = a.get(each)
val_b = b.get(each)
Original Question
I have two sets of tuples, each of the form
a = {(x,y,t), (x,y,t), ...}
b = {(x,y,t), (x,y,t), ...}
I'd like to find the "intersection" of a and b while ignoring the t element of the tuples.
For example:
a = {(1,2,5), (4,6,7)}
b = {(1,2,7), (5,5,3)}
c = a.magicintersection(b,'ignore-last-element-of-tuple-magic-keyword')
where c, the desired output, would yield {(1,2,5), (1,2,7)}.
I'd like to leverage the built-in intersection function rather than writing my own (horribly inefficient) function but I can't see a way around this.
You cant use the built in intersection methods for that. You also can't attach function to built ins:
def magic_intersect(x):
pass
set.mi = magic_intersect
results in
set.mi = magic_intersect
TypeError: can't set attributes of built-in/extension type 'set'
You could prop them all into a dictionary with keys of the 1st two elements of each tuple and values of set/list all tuples that match this to get the result:
a = {(1,2,5), (4,6,7)}
b = {(1,2,7), (5,5,3)}
from collections import defaultdict
d = defaultdict(set)
for x in (a,b):
for s in x:
d[(s[0],s[1])].add(s)
print(d)
print(d.get( (1,2) )) # get all tuples that start with (1,2,_)
Output:
defaultdict(<class 'set'>, {
(4, 6): {(4, 6, 7)},
(1, 2): {(1, 2, 5), (1, 2, 7)},
(5, 5): {(5, 5, 3)}})
{(1, 2, 5), (1, 2, 7)}
but thats only going to be worth it if you need to query for those multiple times and do not need to put millions of sets in them.
The actual "lookup" of what 2-tuple has which 3-tuples is O(1) fast - but you need space/time to build the dictionary.
This approch looses the information from wich set of tuples the items came - if you need to preserve that as well, you would have to store that as well - somehow.
What would your "intersection" have as a result, if the third component varies?
Anyway, the way to do this is to have a dictionary where the key is a tuple with the components of interest. The dictionary values can be lists with all matching 3-tuples, and then you can select just those which have more than one element.
This is not inefficient, you will only have to walk each set once - so it is O(M + N) - and you have a lot of lists and thousands of tuples with the the same x, y - then building the dictionary will append the matching tuples to a list, which is O(1).
matches = {}
for series_of_tuples in (a, b):
for tuple in series_of_tuples:
matches.setdefault(tuple[:2], []).append(tuple)
intersection = [values for values in matches.values() if len(values) > 1]
I have a 3 element tuple where one of the elements is dissimilar from the other two. For example, it could be something like: (0.456, 0.768, 0.456).
What is the easiest way to find the index of this dissimilar element? One way I can think of is consider index (0, 1) and (1, 2) and one of these will be dissimilar. If it is (0, 1) then compare their elements to the element at 2 otherwise, compare elements of (1, 2) to index 0 to find the dissimilar element.
Feels like I am missing a pythonic way to do this.
A simple approach:
def func(arr):
x, y, z = arr
return 2 * (x == y) + (x == z)
Test:
func(['B', 'A', 'A'])
# 0
func(['A', 'B', 'A'])
# 1
func(['A', 'A', 'B'])
# 2
You could count the occurences of each element in the list then find the index of the place where only one element exists but I have a feeling this may not be as performant as your solution. It also wouldn't work if all 3 values are distinct.
my_tuple[[my_tuple.count(x) for x in my_tuple].index(1)]
You could try this:
index = [my_tuple.index(i) for i in my_tuple if my_tuple.count(i) == 1][0]
I'm not sure it is great performance-wise though.
What may look like A huge overkill in python 3, but couldn't help posting:
import collections
a = (0.768, 0.456, 0.456)
print("Dissimilar object index: ", a.index(list(collections.Counter(a).keys())[list(collections.Counter(a).values()).index(1)]))
Explanation:
collections.Counter(a): will return a frequency dict e.g {0.768:1, 0.456:2} etc. Then we just create a list to leverage index(1) to find out the value that's odd one out. Then we use a.index(odd_one_out_val) to find index.
I have a list of tuples like this:
tradeRanges = [(0,3), (10,14), (16,16), (21,23), (25,25)]
What I would like to do is:
Take every tuple and analysing the difference between the two numbers;
If this difference is non-zero, then I'd like to append a third element which is in fact the difference of this two numbers; if it's zero, I'd just like to pull the tuple out of the list.
The final output, hence, would be this:
tradeRanges = [(0,3,3), (10,14,4), (21,23,2)]
With this purpose I have tried to write the following script:
for tups in tradeRanges:
tradeRanges.remove(tups)
tups = list(tups)
lenTup = tups[1]-tups[0]
if lenTup > 0:
tups.append(lenTup) #so when it's done I would have the list into the same order
tups = tuple(tups)
tradeRanges.append(tups)
The problem here is that it skips the elements. When it gets the element (0,3) and remove it, rather than saving in memory the element (10,14) it will save the element (16,16). I have a vague idea of why this happens (probably the for loop is taking care of the positioning of the elements?) but I have no clue how to fix it. Is there any elegant way or I should use some control variables to take into account the position of the elements within the list?
tups = tuple(tups)
tradeRanges.append(tups)
tradeRanges = [(0,3), (10,14), (16,16), (21,23), (25,25)]
print [(n1, n2, abs(n1-n2)) for n1, n2 in tradeRanges if n1 != n2]
# [(0, 3, 3), (10, 14, 4), (21, 23, 2)]
I have two lists of tuples: The first (A) has the value sets I'm checking. The second (B) has combinations of values that I want to weed out if they're present in A.
A = [(1, 2, 3), (6, 10, 8)]
B = [(5, 7, 9), (10, 6)]
As you can see, the checking is complicated by the facts that:
- the B tuples may be shorter than the A tuples
- the B tuples may vary in length
- the values may appear in a different order in a B tuple than they do in an A tuple
- the A tuples all have identical length but that length can't be predetermined
The best way I have come up with to do this involves some redundancy:
bad_tuples = [tup for badtup in B for tup in A
if [baditem for baditem in badtup if baditem in tup]
and len([baditem for baditem in badtup if baditem in tup]) == len(badtup)]
good_tuples = [tup for tup in A if tup not in bad_tuples]
I think this gets the job done, but I don't like the fact that I have to duplicate an identical list comprehension in finding bad_tuples. I also find it hard to read and so error-prone. So can anyone think of a more elegant/efficient way of accomplishing the task?
(If it matters, in my application there are likely to be many (but < 100) tuples in A and only a few (< 10) tuples in B.)
If entries within a tuple are indeed unique, it should be as simple as:
[x for x in A if set(x) not in [set(y) for y in B]]
UPDATE
Based on the comments, it appears that the exclusion should be for all tuples in A of which tuples in B are subsets when everything has been converted to sets. So it's:
[x for x in A if not any([set(y).issubset(set(x)) for y in B])]
This should work.
for tup in B:
if(tup in A):
bad_tuples.append(tup)
else:
good_tuples.append(tup)
Assumed, the order of the elements of the tuples is relevant.