Merging nested lists alternatively [duplicate] - python

This question already has answers here:
Transpose list of lists
(14 answers)
Closed 9 months ago.
Input is [[159,159],[21,21]]
and I need
output like [[159,21],[159,21]]
I have searched python solution and tried a lot still am not getting solution, please share me solution.

Steps
zip the data together
convert the zipped tuple to list using map
convert the whole thing to be a list
Code
data = [[159,159],[21,21]]
print(list(map(list, zip(data[0],data[1]))))
Output
[[159,21],[159,21]]

You can use zip:
in_lists = [[159,159], [21,21]]
out_lists = list(zip(*in_lists))
print(out_lists)
which outputs
[(159, 21), (159, 21)]
The * in zip(*in_lists) will "unpack" the iterator in_lists and feed them to zip as separate arguments, which will be like zip([159, 159], [21, 21]). The zip function then combines the i-th element from all iterables into tuples, which results in [(159, 21), (159, 21)].

zip will do just that:
lst = [[159, 159], [21, 21]]
lst2 = list(zip(*lst))
print(lst2) # [(159, 21), (159, 21)]
if you need the nested elements to be lists as well:
lst2 = [list(item) for item in zip(*lst)] # [[159, 21], [159, 21]]

Related

List of integers to pairs of tuples [duplicate]

This question already has answers here:
Splitting a Python list into a list of overlapping chunks
(3 answers)
How can I iterate over overlapping (current, next) pairs of values from a list?
(12 answers)
Closed 3 months ago.
I have a list of integers like this
numbers = [1, 5, 7, 19, 22, 55]
I want to have a function that takes this as input and gives me a list of paired tuples that should contain the numbers as (1,5), (5,7), (7,19) and so on.
Kindly suggest.
I have tried using for loops. Didn't get expected output.
From Python 3.10 you can use itertools.pairwise
from itertools import pairwise
numbers = [1, 5, 7, 19, 22, 55]
list(pairwise(numbers)) # [(1, 5), (5, 7), (7, 19), (19, 22), (22, 55)]
lst = [(numbers[i],numbers[i+1]) for i in range(0,len(numbers)-1)]
This should do the trick: loop over all elements in the list numbers. You loop until the one to last element, since otherwise you would walk out of the array (get an index error).

Find gaps in list of range values

I found numerous similar questions in other programming languages (ruby, C++, JS, etc) but not for Python. Since Python has e.g. itertools I wonder whether we can do the same more elegantly in Python.
Let's say we have a "complete range", [1,100] and then a subset of ranges within/matching the "complete range":
[10,50]
[90,100]
How can we extract the not covered positions, in this case [1,9], [51,89]?
This is a toy example, in my real dataset I have ranges up to thousands.
Here is a neat solution using itertools.chain: I've assumed the input ranges don't overlap. If they do, they need to be simplified first using a union-of-ranges algorithm.
from itertools import chain
def range_gaps(a, b, ranges):
ranges = sorted(ranges)
flat = chain((a-1,), chain.from_iterable(ranges), (b+1,))
return [[x+1, y-1] for x, y in zip(flat, flat) if x+1 < y]
Taking range_gaps(1, 100, [[10, 50], [90, 100]]) as an example:
First sort the ranges in case they aren't already in order. If they are guaranteed to be in order, this step is not needed.
Then flat is an iterable which will give the sequence 0, 10, 50, 90, 100, 101.
Since flat is lazily evaluated and is consumed by iterating over it, zip(flat, flat) gives a sequence of pairs like (0, 10), (50, 90), (100, 101).
The ranges required are then like (1, 9), (51, 89) and the case of (100, 101) should give an empty range so it is discarded.
Assuming the list contains only integers, and the sub-ranges are in increasing order and not overlapping, You can use below code.
This code will take all sub ranges one by one, and will compare with original complete range and the sub range before it, to find the missing range.
[start,end]=[1,100]
chunks=[[25,31],[7,15],[74,83]]
print([r for r in [[start,chunks[0][0]-1] if start!=chunks[0][0] else []] + [[chunks[i-1][1]+1, chunks[i][0]-1] for i in range(1,len(chunks))]+[[chunks[-1][1]+1,end] if end!=chunks[-1][1] else []] if r])
Input
[1,100]
[[7,15],[25,31],[74,83]]
Output
[[1, 6], [16, 24], [32, 73], [84, 100]]
If increasing order of sub ranges are not guaranteed. you can include below line to sort chunks.
chunks.sort(key=lambda x: x[0])
This is a generic solution:
def gap(N, ranges):
ranges=[(min1, max1), (min2, (max2), ......, (minn, maxn)]
original=set(range(N))
for i in ranges:
original=original-set(range(i[0], i[1]))
return original

Remove duplicated tuples from list based on the first entry of tuple [duplicate]

This question already has answers here:
Remove partially duplicate tuples from list of tuples
(3 answers)
Making a sequence of tuples unique by a specific element
(1 answer)
Closed 3 years ago.
I have a list of tuples like this one here:
test = [('ent1', 24), ('ent2',12), ('ent3',4.5), ('ent1', 4), ('ent2', 3.5)]
I would like to remove those tuples from the list where the first element has already appeared. So the desired output would be
[('ent1', 24), ('ent2',12), ('ent3',4.5)]
I have no idea how to do this. Normally, if I would like to remove exact duplicated tuples, I would use
list(set(test))
but this is not working in this case. Has anybody an appropriate approach for this problem?
How do you like the output of dict(test)?
{'ent1': 4, 'ent2': 3.5, 'ent3': 4.5}
Or you may want to convert this back to a list of tuples with
>>> list(dict(test).items())
[('ent1', 4), ('ent2', 3.5), ('ent3', 4.5)]
Edit: This will keep the last assigned value but you can also keep the first assigned value by reversing first your list:
>>> list(dict(reversed(test)).items())
[('ent2', 12), ('ent1', 24), ('ent3', 4.5)]
Edit2: If you want to preserve list order, as well, this seems to be a good one-liner solution (inspired by Julien's answer):
>>> [(uk,next(v for k,v in test if k == uk)) for uk in dict(test).keys()]
[('ent1', 24), ('ent2', 12), ('ent3', 4.5)]
And finally, you with functools.reduce you can get another one-liner:
>>> from functools import reduce
>>> reduce(lambda lu,i:i[0] in dict(lu).keys() and lu or lu+[i], test, [])
[('ent1', 24), ('ent2', 12), ('ent3', 4.5)]
Explanation: lu is the list with only unique keys, i is the next item from the test list. If i[0], i.e. the key of the next element is in lu already, we keep lu, otherwise we append i.
Using a check flag
Ex:
test = [('ent1', 24), ('ent2',12), ('ent3',4.5), ('ent1', 4), ('ent2', 3.5)]
check_val = set() #Check Flag
res = []
for i in test:
if i[0] not in check_val:
res.append(i)
check_val.add(i[0])
print(res)
Output:
[('ent1', 24), ('ent2', 12), ('ent3', 4.5)]
test = [('ent1', 24), ('ent2',12), ('ent3',4.5), ('ent1', 4), ('ent2', 3.5)]
deduplicated_test = [(s,[t[1] for t in test if t[0] == s][0]) for s in sorted(set([t[0] for t in test]))]
Short and painful to read, sorry.
I don't remember why sorted(set()) works and set() doesn't but anyway...

intercept dictionary items which are two dimensional array

Here is my dictionary of n items.
{
"proceed": [[6,46] , [7,67], [12,217], [67,562], [67,89]],
"concluded": [[6,46] , [783,123], [121,521], [67,12351], [67,12351]],
...
}
imagine a dictionary s.t. like that with n keys and items which are two dimensional arrays.
I want to intercept all of them and take the result as [6,46]
I tried s.t. like that :
result=set.intersection(*map(set,output.values()))
however it got error because of items are two dimensinal array.
Can someone please help me how to do that ?
Thanks.
So... sets don't work for lists because lists are not hashable. Instead you'll have to make them sets of tuples like so:
result = set.intersection(*({tuple(p) for p in v} for v in output.values()))
Edit: works in py version >= 2.7
Completely agree with answer of #FHTMitchell but here's a bit of more explanation with example of why you can't get unique set with list and get TypeError: unhashable type
Consider below values:
x = {'concluded': [[6, 46], [783, 123], [121, 521], [67, 12351], [67, 12351]],
'proceed': [[6, 46], [7, 1], [12, 217], [67, 562], [67, 89]]}
y = {'concluded': ((6, 46), (67, 12351), (121, 521), (783, 123)),
'proceed': ((6, 46), (7, 1), (12, 217), (67, 89), (67, 562))}
x is the dictionary containing list of list as values; the main thing to note is that value of keys are stored as list which is mutable; but in y it's tuple of tuples or you may keep it as set which is not mutable
Now consider some how you managed to get your desire output [6,46] but if you notice it's a list contains some elements stored in a list so if you change the values as below:
x['proceed'][0][0] = 9
it will change your value [6, 46] to [9,46] in concluded key and now your output may or may not change which depends on how you iterated and stored it.

Randomly assign each of the coordinates [a,b] with each of the elements in a list

GRIDCOLS = 3;
GRIDROWS = 4 ;
gidder = 20;
gridxy = [];
for column in range (GRIDCOLS):
.. yrow = column * 100+ 50
.. for row in range (GRIDROWS):
.. xcell = row * 100+50
.. ycell = yrow + random.randint(-gidder, gidder)
.. gridxy.append([xcell, ycell])
.. print (gridxy)
this would create something like this [50, 58], [150, 56], [250, 39], [350, 52]
sumlist = ['a','b','c','$','4','2','3']
and what i want to do is assigning each of the coordinates [a,b] with each of the elements within the sumlist randomly.
I'm not really sure how to approach this. Do i do something with the index? Please help.
Thank you.
What kind of assignment do you need?
You can use zip([iterable, ...])
This function returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables.
>>> zip(sumlist, gridxy)
[('a', [50, 58]), ('b', [150, 56]), ('c', [250, 39]), ('$', [350, 52])]
You can create a dict:
>>> dict(zip(sumlist, gridxy))
{'a': [50, 58], 'b': [150, 56], 'c': [250, 39], '$': [350, 52]}
If you need a ordered dictionary you can use collections.OrderedDict
Return an instance of a dict subclass, supporting the usual dict methods.
You must random.shuffle your data...
import random
sumlist = ['a','b','c','$','4','2','3']
random.shuffle(sumlist) # shuffles in place!
At this point you have a random permutation of your data, stored into sumlist and you can proceed with pairing the sumlist and the gridxy elements, usually using the zip builtin (that truncates the pairing at the shortest iterable's length) or zip_longest in the itertools module that allow you to use a default value as a fill-in.
# create a list of tuples
lot = [t for t in zip(sumlist,gridxy)]
# create a dict
d = {s:xy for s, xy in zip(sumlist,gridxy)}
Of course you can use zip_longest if you feel appropriate to use default values in your code.
Pay attention to the fact that random.shuffle operates in place (and returns None), so that if you want to access your data in the original order, then you want to save it somewhere before shuffling
...
original_list = sumlist[:]
random.shuffle(sumlist)
...

Categories

Resources