Extend tuples in one list using tuples from another list - python

I have two lists. Both lists will have the same sets of rows. I would like to add list2 columns to list1 to create one list.
list1 = [('gi1','1','2'),
('gi1','1','2'),
('gi1','1','2')]
list2 = [('a','b','c','d','e','f','g'),
('a','b','c','d','e','f','g'),
('a','b','c','d','e','f','g')]
I would like to merge these into a list that looks like this:
[('gi1','1','2','a','b','c','d','e','f','g'),
('gi1','1','2','a','b','c','d','e','f','g'),
('gi1','1','2','a','b','c','d','e','f','g')]

I would use the help of itertools.chain
>>> list1=[('gi1','1','2'),
('gi1','1','2'),
('gi1','1','2')]
>>> list2=[('a','b','c','d','e','f','g'),
('a','b','c','d','e','f','g'),
('a','b','c','d','e','f','g')]
>>> from itertools import chain
>>> [tuple(chain(x, y)) for x, y in zip(list1, list2)]
[('gi1', '1', '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g'), ('gi1', '1', '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g'), ('gi1', '1', '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g')]

If you know that both lists have the same length:
[list1[i] + list2[i] for i in range(len(list1))]

Another way to do it. Use Zip()
>>> [e1+e2 for e1,e2 in zip(list1,list2)]
[('gi1', '1', '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g'), ('gi1', '1', '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g'), ('gi1', '1', '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g')]

Related

How to re-order and expand lists to have same size?

I am trying to re-order and extend lists of dictionary values with the right position and fill them with zeros.
myDict = {
"col-1": ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
"col-2": ['a', 'b', 'c', 'd', 'f', 'e']
}
The desired output should look like this:
myDict = {
"col-1": ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
"col-2": ['a', 'b', 'c', 'd', 'e', 'f', '0'] # '0' is zero
}
Note that values of lists are with order 'a', 'b', 'c', 'd', 'e', 'f', 'g'. The maximum list length in myDict.values() is fixed to 7 and the minimum is 6. myDict can have more than two elements.
I tried to use Python - extending and filling list with zeros to match another list but didn't know exactly how to make it work for my case.
Assuming the maximum length is 7 and values are only single characters from "a" to "g"
myDict = {
"col-1": ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
"col-2": ['a', 'b', 'c', 'd', 'e', 'f']
}
for key, value_list in myDict.items():
new_value_list = [0 for i in range(7)]
for value in value_list:
new_value_list[ord(value) - 97] = value
myDict[key] = new_value_list
print(myDict)
This should cover the cases identified in the original post and the clarification comment. The approach is, for each key of the dict, to iterate over the set of valid letters, outputting that letter (if it exists in the dict value), or '0' (if it doesn't).
myDict = {
"col-1": ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
"col-2": ['a', 'b', 'c', 'd', 'f', 'e'],
"col-3": ['a', 'c', 'f'],
"col-4": ['b', 'd']
}
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
for key, value in myDict.items():
myDict[key] = [(x if x in value else '0') for x in letters]
print(f"{key}: {myDict[key]}")
prints:
col-1: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
col-2: ['a', 'b', 'c', 'd', 'e', 'f', '0']
col-3: ['a', '0', 'c', '0', '0', 'f', '0']
col-4: ['0', 'b', '0', 'd', '0', '0', '0']
seems to me that you could do this with a for-while loop:
for key in myDict.keys():
myDict[key] = sorted(myDict[key])
while len(myDict[key])<len(myDict["column1"]):
myDict[key].append('0')

Find all combinations of a list with different elements removed each time

I need a way to find all combinations from two different lists where each element may or may not be null. For example with the two lists I'd like to call a function that returns a list of all these combinations:
a = ['A', 'S', 'B']
b = ['A', 'B']
find_combinations(a, b)
Should return:
[['A', 'S', 'B'], ['A', 'S'], ['S', 'B'], ['S']]
I can do this trivial example but if the list is more complicated say ['A', 'B', 'S', 'A', 'A'] then the possible options are much more complicated:
[['A', 'B', 'S', 'A', 'A'],
['A', 'B', 'S', 'A'],
['A', 'B', 'S', 'A'],
['B', 'S', 'A', 'A']
... etc.
I will assume the elements of b are hashable. In that case you can use the following code:
def without(a,i,bi,l):
if i >= len(a):
yield tuple(l)
else:
l.append(a[i])
for result in without(a,i+1,bi,l):
yield result
l.pop()
if a[i] in bi:
for result in without(a,i+1,bi,l):
yield result
def find_combinations(a, b):
for result in without(a,0,set(b),[]):
yield result
Here we first convert the b into a set to boost performance. This is strictly speaking not necessary. Then we use a recursive algorithm where for each element a[i] in a that is in b, we have a decision point whether to or not to include it in the result (that's why we perform the recursion again when that element is popped). When we reach the end of the list, we convert our running list l into a tuple(..). You can also use list(..) to convert it into a list.
We use a running list to boost performance a bit since concatenating two lists is done in O(n) whereas the running list can append(..) and pop(..) in O(1) amortized cost.
This will produce a generator of tuples. You can materialize the outcome of each generator with list(..) like:
>>> list(find_combinations(['A','S','B'],['A','B']))
[('A', 'S', 'B'), ('A', 'S'), ('S', 'B'), ('S',)]
>>> list(find_combinations(['A', 'B', 'S', 'A', 'A'],['A','B']))
[('A', 'B', 'S', 'A', 'A'), ('A', 'B', 'S', 'A'), ('A', 'B', 'S', 'A'), ('A', 'B', 'S'), ('A', 'S', 'A', 'A'), ('A', 'S', 'A'), ('A', 'S', 'A'), ('A', 'S'), ('B', 'S', 'A', 'A'), ('B', 'S', 'A'), ('B', 'S', 'A'), ('B', 'S'), ('S', 'A', 'A'), ('S', 'A'), ('S', 'A'), ('S',)]
In case lists are required, you can use map(list,..) to convert them to lists, like:
>>> list(map(list,find_combinations(['A','S','B'],['A','B'])))
[['A', 'S', 'B'], ['A', 'S'], ['S', 'B'], ['S']]
>>> list(map(list,find_combinations(['A', 'B', 'S', 'A', 'A'],['A','B'])))
[['A', 'B', 'S', 'A', 'A'], ['A', 'B', 'S', 'A'], ['A', 'B', 'S', 'A'], ['A', 'B', 'S'], ['A', 'S', 'A', 'A'], ['A', 'S', 'A'], ['A', 'S', 'A'], ['A', 'S'], ['B', 'S', 'A', 'A'], ['B', 'S', 'A'], ['B', 'S', 'A'], ['B', 'S'], ['S', 'A', 'A'], ['S', 'A'], ['S', 'A'], ['S']]
After playing around I found an alternative way to Willem Van Onsem's answer. Not quite as clean but also works.
def empty_derivations(rule, empty_list):
returned = []
returned.append(rule)
for element in returned:
for num, char in enumerate(element):
temp = element[:]
if char in empty_list:
del temp[num]
returned.append(temp)
return_list = []
for element in returned:
if element not in return_list:
return_list.append(element)
return return_list
When called gives:
>>> a = empty_derivations(['A', 'B', 'S', 'A', 'A'], ['A', 'B'])
>>> print(a)
[['A', 'B', 'S', 'A', 'A'],
['B', 'S', 'A', 'A'],
['A', 'S', 'A', 'A'],
['A', 'B', 'S', 'A'],
['S', 'A', 'A'],
['B', 'S', 'A'],
['A', 'S', 'A'],
['A', 'B', 'S'],
['S', 'A'],
['B', 'S'],
['A', 'S'],
['S']]

How to generate a sequence where each element is separated from an identical element by at least six different elements

From a list of 8 possible letters I want to generate a random sequence where each element is separated from an identical element by at least six different elements.
sequence_list = []
target_list = ["a","b","c","d","e","f","g","h"]
for i in range(1,41):
sequence_list.append(random.choice(target_list))
print sequence_list
For example if the first letter in sequence_list is an a it should not be repeated for at least the next 6 items in the list. Same for every other item.
Appreciate your help.
this is probably not the most efficient way of doing it, but you can do it like this:
>>> target_list = list(string.ascii_letters[:8])
>>> target_list
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> sequence_list = []
>>> for i in range(1,41):
... el_list = [x for x in target_list if x not in sequence_list[-6:]]
... sequence_list.append(random.choice(el_list))
...
>>>
>>> sequence_list
['e', 'h', 'g', 'a', 'c', 'f', 'd', 'b', 'e', 'h', 'g', 'c', 'f', 'd', 'a', 'e', 'b', 'g', 'c', 'f', 'h', 'a', 'e', 'b', 'g', 'd', 'f', 'c', 'h', 'a', 'b', 'g', 'd', 'f', 'e', 'c', 'a', 'b', 'h', 'd']

Python merge second part of tuple list into list of strings

I have only recently started learning Python, and I have looked at similar questions and cannot seem to find an example that helps - I have this list of tuples currently:
[('E', ['E', 'F', 'C', 'C']), ('F', ['A', 'D', 'D', 'B']), ('I', ['F', 'D', 'F', 'D']), ('R', ['E', 'B', 'D', 'B']), ('S', ['B', 'C', 'C', 'D'])]
and I want to split them up into a list of strings, so that they look like this:
['EFCC', 'ADDB', 'FDFD', 'EBDB', 'BCCD']
I have tried to use the '.join' function for this, as shown below:
stringList = "".join([str(x[1]) for x in sortedList])
but this provides me with a list in the form:
['B', 'D', 'E', 'C']['B', 'C', 'B', 'D']['E', 'C', 'D', 'C']['B', 'C', 'D', 'C']['C', 'E', 'F', 'A']
I think I am using the join method wrong, but after changing a few bits about in it, I can't figure out how to get the format I want.
Your problem is str(x[1]).
x[1] is a list, and you convert it to a string:
>>> x = ('E', ['E', 'F', 'C', 'C'])
>>> x[1]
['E', 'F', 'C', 'C']
>>> str(x[1])
"['E', 'F', 'C', 'C']"
What you want is to join the elements of the list:
>>> ''.join(x[1])
'EFCC'
So your code would become:
[''.join(x[1]) for x in sortedList]
Use a list comprehension and join the strings, like so.
t = [('E', ['E', 'F', 'C', 'C']), ('F', ['A', 'D', 'D', 'B']), ('I', ['F', 'D', 'F', 'D']), ('R', ['E', 'B', 'D', 'B']), ('S', ['B', 'C', 'C', 'D'])]
x = [''.join(b) for a, b in t]
print(x)
You can use map:
print map(lambda x: "".join(x[1]),t)
Output:
['EFCC', 'ADDB', 'FDFD', 'EBDB', 'BCCD']

python compare values of the sublists of a list and add up values

I have a list with an unknown number of sublists.
I want to compare always one sublist with ALL other sublists.
If the values of the first sublist at position 0, 3 and 5 are equal to any other sublist, I want to to add together the values at position 7 in all matching lists.
And then add this first sublist with the (newly added up value) at position 7 to a new list.
list = [['A', 'a', 'b', 'B', 'c', 'd', 'C', '1'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '3'],
['D', 'r', 's', 'E', 't', 'u', 'F', '2'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '2'],
['D', 'r', 's', 'E', 't', 'u', 'F', '2'],.....]
wanted Output:
new_list = [['A', 'a', 'b', 'B', 'c', 'd', 'C', '6'],
['D', 'r', 's', 'E', 't', 'u', 'F', 4],...]
I wrote this code
def Inter(list):
a = 0
b = 3
c = 5
d = 0
x = []
for i in range(len(list)):
for y in range(len(list)):
if list[i][a] == list[y][a] and list[i][b] == list[y][b] and list[i][c] == list[y][c]:
IntSumtemp = []
IntSumtemp.append(str(float(list[i][7]) + float(list[y][7])))
x.append(list[i] + IntSumtemp)
del (x[d][7])
d +=1
else: None
return x
new_list= Inter(list)
but it gave this output:
new_list= [['A', 'a', 'b', 'B', 'c', 'd', 'C', '2.0'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '4.0'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '3.0'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '4.0'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '6.0'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '5.0'],
['D', 'r', 's', 'E', 't', 'u', 'F', '4.0'],
['D', 'r', 's', 'E', 't', 'u', 'F', '4.0'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '3.0'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '5.0'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '4.0'],
['D', 'r', 's', 'E', 't', 'u', 'F', '4.0'],
['D', 'r', 's', 'E', 't', 'u', 'F', '4.0']]
Can someone help me with this, please?
(Sorry, I am a absolute beginner, so if anything is unclear, plz ask...)
This approach is O(N) as opposed to yours which was O(N^2)
from collections import OrderedDict
from operator import itemgetter
items = [['A', 'a', 'b', 'B', 'c', 'd', 'C', '1'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '3'],
['D', 'r', 's', 'E', 't', 'u', 'F', '2'],
['A', 'a', 'b', 'B', 'c', 'd', 'C', '2'],
['D', 'r', 's', 'E', 't', 'u', 'F', '2']]
key = itemgetter(0, 3, 5)
d = OrderedDict()
for x in items:
d.setdefault(key(x), x[:7] + [0])[7] += int(x[7])
print d.values()
[['A', 'a', 'b', 'B', 'c', 'd', 'C', 6], ['D', 'r', 's', 'E', 't', 'u', 'F', 4]]

Categories

Resources