Append difference of elements in tuples in list - python

If I have a list such as [(10, 22), (12, 50), (13, 15)] and would like to append the difference of these numbers so that the list would look like [(12, 10, 22), (38, 12, 50), (2, 13, 15)] how can I do this?
I have this line of code newList = [[???]+list(tup) for tup in list] but am not sure what to put where the question marks are to get what I want.
Thanks a lot

tuples can't be modified (they are immutable). So you will have to create new tuples. It looks like you are prepending the difference rather than appending.
newList = [(b-a, a,b) for (a,b) in oldList]

Related

mantain a sum in list comprehension?

this is my code
def width2colspec(widths):
tupleback = []
a=0
for w in widths:
b=a+w
tupleback.append((a,a+w))
a=b
return tupleback
eg:
widths=[15,9,50,10]
width2colspec(widths)
Result:
[(0, 15), (15, 24), (24, 74), (74,84)]
(first one always has to be a zero)
It works and all(maybe not very elegant tho)
To practice I tried to convert it into a list comprehension one liner but i couldn't make it work, closest i got was this.
widths=[15,9,50,10]
colspecs=list((widths[i],widths[i]+widths[i+1]) for i in range(len(widths)-1))
result:
[(0, 15), (15, 24), (9, 59), (50,60)]
(its not maintaining the sum trough the loop)
So my question is, is it possible?
You can do this as a pure list comprehension, but it involves a lot of re-computation, so I wouldn't recommend actually doing it this way.
Start by building a list of all the sums (note that this is re-summing the same numbers over and over, so it's less efficient than your original code that keeps a running sum):
>>> [sum(widths[:i]) for i in range(len(widths)+1)]
[0, 15, 24, 74, 84]
and then iterate over that to produce your list of tuples:
>>> [tuple([sum(widths[:i]) for i in range(len(widths)+1)][i:i+2]) for i in range(len(widths))]
[(0, 15), (15, 24), (24, 74), (74, 84)]
Note that we're now re-computing all those sums again because we didn't assign the original list to a variable.
If you're using Python 3.8 or later, you can use an assignment expression (utilizing the walrus operator :=) to do this in a single list comprehension. I'm "cheating" a little by initializing last via a default argument, but this isn't strictly necessary (I just wanted to make it a "one-liner").
def width2colspec(widths, last=0):
return [(last, last := last+width) for width in widths]
I don't find it that confusing, to be honest.

Combining a list of onset-offset tuples if the previous element's offset equals the next element's onset

Is there any standard library Python or Numpy operation for doing the following:
my_array = [(1, 3), (3, 4), (4, 5), (5, 7), (10, 12), (12, 17), (21, 24)]
new_array = magic_function(my_array)
print(new_array)
> [(1, 7), (10, 17), (21, 24)]
I feel like something in itertools should be able to do this, seems like something a lot of people would use. We can assume the list is sorted by onset times already. It wouldn't be hard to do that anyway, you'd just use the sorted function with a key on the first element.
Apologies if this question has already been asked, wasn't sure how to word this problem, but this could be seen as a list of onsets and offsets and I want to merge elements with adjacent/equivalent timing.
EDIT: Inspired by #chris-charley's answer below, which relies on some third party module, I just wrote up a small function which does what I wanted.
import re
def magic_function(mylist):
# convert list to intspan
intspan = ','.join([f'{int(a)}-{int(b)}' for (a,b) in mylist])
# collapse adjacent ranges
intspan = re.sub(r'\-(\d+)\,\1', '', intspan)
# convert back to list
return [tuple(map(int, _.split('-'))) for _ in intspan.split(',')]
Here is the same function generalized for floats also:
import re
def magic_function(mylist):
# convert list to floatspan
floatspan = ','.join([f'{float(a)}-{float(b)}' for (a,b) in mylist])
# collapse adjacent ranges
floatspan = re.sub(r'\-(\d+\.?\d+?)+\,\1', '', floatspan)
# convert back to list
return [tuple(map(float, _.split('-'))) for _ in floatspan.split(',')]
intspan has the methods from_ranges() and ranges() to produce the results you need.
>>> from intspan import intspan
>>> my_array = [(1, 3), (3, 4), (4, 5), (5, 7), (10, 12), (12, 17), (21, 24)]
>>> intspan.from_ranges(my_array).ranges()
[(1, 7), (10, 17), (21, 24)]

How to concatenate a pair of coordinates within a sublist consecutively in python?

I have the following list of coordinates:
coords=[[(1,2),(3,4),(5,6)], [(7,8),(9,10)], [(11,12),(13,14),(15,16),(17,18)]]
I would like to convert it to a following list if possible using itertools python (not necessarily):
coords=[((1,2),(3,4)), ((3,4),(5,6)), ((7,8),(9,10)), ((11,12),(13,14)), ((13,14),(15,16)), ((15,16),(17,18))]
Thank you
I have tried the following for iterating over one list but not nested list:
zip(coords[:-1],coords[1:]
You can use a nested list comprehension. Pair adjacent tuples in each sub-list by zipping the sub-list with itself but with an offset of 1:
[p for t in coords for p in zip(t, t[1:])]
This returns:
[((1, 2), (3, 4)), ((3, 4), (5, 6)), ((7, 8), (9, 10)), ((11, 12), (13, 14)), ((13, 14), (15, 16)), ((15, 16), (17, 18))]

Why is my list of Tuples vertical?

I believe I've made an error in my coding in where my list of tuples prints out vertically instead of the correct way. May someone please tell me what's up?
This is the question being asked:
Enumerate It!
Write a function called enum that takes a sequence and returns a list of 2-tuples with each tuple holding the index and its associated item.
This is the example given:
>>> enum([45,67,23,34,88,12,90])
[(0, 45), (1, 67), (2, 23), (3, 34), (4, 88), (5, 12), (6, 90)]
>> enum('hello')
[(0, 'h'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o')]
This is my code:
def enum(aSequence):
for i in range(7):
b=aSequence[i]
a= [i]
list1 = [a,b]
print (list1)
If following the example input is used this is the result:
[[0], 45]
[[1], 67]
[[2], 23]
[[3], 34]
[[4], 88]
[[5], 12]
[[6], 90]
The result I would desire is:
[(0, 45), (1, 67), (2, 23), (3, 34), (4, 88), (5, 12), (6, 90)]
When I take away print(list1) and use return list1 instead this is the result.
[[0], 13]
Why is this the case?
When I put this into the website in which I'm being tutored on, the word "Jack and Jane" is displayed and random numbers are shown if a different test. My second question is how do I get the range loop to fit based on the parameter input. I tried to import math and import random. While both are short term solutions they aren't long term solutions.
I feel like I'm overthinking the problem as the code is there just the basic fundamentals might be missing.
The question asks you to return a list with the desired structure, so be careful about that. You are just printing one right now.
def enum(aSequence):
list1 = []
for i in range(len(aSequence)):
b = aSequence[i]
a = i
# use append to keep your items in the list to be returned
list1.append((a, b))
return list1
print(enum('hello')) # this should print horizontally like you asked.
Regarding the simplest answer to create the list you want, the enumerate function is your friend. The enumerate function unpacks a tuple of the index and the object found at the index for an iterable.
thing = 'hello there!'
#typical use case for enumerate
for i, item in enumerate(thing):
print(i, item)
So here's an example function that does what you want...
def enum(iterable):
# must use list() to cast it as an object or else we return a generator object
return list(enumerate(iterable))
enum('hello there!')
You are almost correct. The problem is with your a=[i]. By using [] brackets you are creating a list, so a is a list, instead of an int.
Change a=i and it will be fine. Also hardcoded range(7) should be changed to range(len(aSequence)). The ideal solution for you would be something like:
def enum(aSequence):
result = []
for i in range(len(aSequence)):
result.append((i, aSequence[i]))
return result
What you need to remember is the fact, that print is not a return.
This is how it should be. You need to create the list before starting the loop.Just like below
def enum(aSequence):
list1 = []
for i in range(len(aSequence)):
b = aSequence[i]
a = i
list1.append((a,b))
print list1
enum([45,67,23,34,88,12,90])
This is what you need to print everything in the same line
for i in range(len(aSequence)):
b=aSequence[i]
a= i
list1 = [a,b]
print (list1,end=' ')
Since you wanted the result
[(0, 45), (1, 67), (2, 23), (3, 34), (4, 88), (5, 12), (6, 90)]

How to access lists inside a tuple inside a list in python

I am a newbie to python. Trying to learn how to access Lists inside a Tuple inside a List. My List is:
holidays = [(0,),
(1, [2, 16]),
(2, [20]),
(4, [14]),
(5, [29]),
(7, [4]),
(9, [4]),
(11, [23, 24]),
(12, [25])]
I would like to know the best way to access each tuple and its list in a more efficient way. I tried using:
for i, tuples in enumerate(holidays):
for list in tuples:
print list
But i get the following error:
for list in tuples:
TypeError: 'int' object is not iterable
Help would be much appreciated.
You need to remove the i in the first for loop:
for tuples in enumerate(holidays):
for list in tuples:
print list
short version
[y for x in holidays if isinstance(x, tuple) for y in x if isinstance(y, list)]
You can't do a for .. in LOOP on an integer, that's why the program cras
Well, your holidays list is not uniform: the first entry is an integer (0), the others are tuples.
holidays = [0, # <- integer
(1, [2, 16]),
(2, [20]),
(4, [14]),
(5, [29]),
(7, [4]),
(9, [4]),
(11, [23, 24]),
(12, [25])]
Here is a possible loop:
for entry in holidays:
if entry == 0:
continue # don't know what to do with zero
month, days = entry
print(month, days)
We use unpaking to extract the month and the days.
See Tuples and Sequences in the Python tutorial.
Change your first element 0 to (0), Also, remove 'i' from your for loop, as told by Stavros, it will work.
holidays = [([0]),
(1, [2, 16]),
(2, [20]),
(4, [14]),
(5, [29]),
(7, [4]),
(9, [4]),
(11, [23, 24]),
(12, [25])]
tuples in enumerate(holidays):
list in tuples:
print list

Categories

Resources