I have a list of strings
X=['kmo','catlin','mept']
I was trying to write a loop that would return a list that contains lists of every Nth letter of each word:
[['k','c','m'], ['m','a','e'],['o','t','p']]
But all the methods I tried only returned a list of all the letters returned consecutively in one list:
['k','m','o','c','a','t','l','i'.....'t']
Here is one version of my code:
def letters(X):
prefix=[]
for i in X:
j=0
while j < len(i):
while j < len(i):
prefix.append(i[j])
break
j+=1
return prefix
I know I'm looping within each word, but I'm not sure how to correct it.
It seems that the length of the resulting list is dictated by the length of the smallest string in the original list. If that is indeed the case, you could simply do it like this:
X = ['kmo','catlin','mept']
l = len(min(X, key=len))
res = [[x[i] for x in X] for i in range(l)]
which returns:
print(res) # -> [['k', 'c', 'm'], ['m', 'a', 'e'], ['o', 't', 'p']]
or the even simpler (kudos #JonClemens):
res = [list(el) for el in zip(*X)]
with the same result. Note that this works because zip automatically stops iterating as soon as one of its elements is depleted.
If you want to fill the blanks so to speak, itertools has got your back with its zip_longest method. See this for more information. The fillvalue can be anything you chose; here, '-' is used to demonstrate the use. An empty string '' might be a better option for production code.
res = list(zip_longest(*X, fillvalue = '-'))
print(res) # -> [('k', 'c', 'm'), ('m', 'a', 'e'), ('o', 't', 'p'), ('-', 'l', 't'), ('-', 'i', '-'), ('-', 'n', '-')]
You can use zip.
output=list(zip(*X))
print(output)
*X will unpack all the elements present in X.
After unpacking I'm zipping all of them together. The zip() function returns a zip object, which is an iterator of tuples where the first item in each passed iterator is paired together, and then the second item in each passed iterator are paired together etc. Finally, I wrapped everything in a list using list.
output
[('k', 'c', 'm'), ('m', 'a', 'e'), ('o', 't', 'p')]
If you want output to be a list of lists. Then use map.
output=list(map(list,zip(*X)))
print(output)
output
[['k', 'c', 'm'], ['m', 'a', 'e'], ['o', 't', 'p']]
X=['kmo','catlin','mept']
y = []
j=0
for i in X:
item =''
for element in X :
if (len(element) > j):
item = item + element[j]
y.append(item)
j=j+1
print("X = [",X,"]")
print("Y = [",y,"]")
try this
def letters(X):
prefix=[]
# First lets zip the list element
zip_elemets = zip(*X)
for element in zip_elemets:
prefix.append(list(element))
return prefix
Related
How to add a variable to each tuple's item that is all ready in a tuple and make the item and the variable a tuple.
Input:
x = (('U', 'H', 'S', 'H'), ('H', 'U', 'H', 'S'), ('U', 'H', 'H', 'U'))
Wanted output:
y = ((('U',0), ('H',0), ('S',0), ('H',0)), (('H',0), ('U',0), ('H',0), ('S',0)), (('U',0), ('H',0), ('H',0), ('U',0)))
I tried to convert it into a dictionary and then back to a tuple but it seemed inefficient. Is there a better way of doing so?
Use generator:
y = tuple(tuple((sub_el, 0) for sub_el in el) for el in x)
It looks like a game but I need this to evaluate a model I'm working on. Need some help...
I have a dictionary with lists as values. I need to replace only one element in each list at a random position with an element in my_list but which is not present in the list.
Then I need to print which letters were swapped preferably as a list of tuples showing each key from the original dictionary.
My code so far, which doesn't work as needed...:
my_list=[['a','b','c','d','e','q'],['f','j','k','l','m','n'],['o','p','r','s','t','k'], ['e','s','w','x','h','z']]
my_dict = {0:['a','d','f'], 1:['o','t','e'], 2:['m', 'j', 'k'],3:['d','z','f']}
all_letters = set(itertools.chain.from_iterable(my_list))
replace_index = np.random.randint(0,3,4)
print(replace_index)
dict_out = my_dict.copy()
replacements = []
for key, terms in enumerate(my_list):
print(key)
print(terms)
other_letters = all_words.difference(terms)
print(other_letters)
replacement = np.random.choice(list(other_letters))
print(replacement)
replacements.append((terms[replace_index[key]], replacement))
print(replacements)
dict_out[replace_index[key]] = replacement
print(dict_out)
print(replacements) # [(o,('a','c')...]
If I understand correctly, you could do something like this:
import numpy as np
for i, k in enumerate(my_dict):
# Pick a random element of your list in each key of my_dict:
original = my_dict[k][np.random.randint(0, len(my_dict[i]))]
# Pick a random element of the corresponding list, that is not in the my_dict key
replacement = np.random.choice(list(set(my_list[i]) - set(my_dict[k])), 1)[0]
# Replace the original for the replacement
my_dict[k][my_dict[i].index(original)] = replacement
# Print what was switched
print((k,(original, replacement)))
The output is:
(0, ('a', 'e'))
(1, ('t', 'm'))
(2, ('m', 't'))
(3, ('f', 'h'))
And your my_dict now looks like:
{0: ['e', 'd', 'f'], 1: ['o', 'm', 'e'], 2: ['t', 'j', 'k'], 3: ['d', 'z', 'h']}
The goal was to create a list of all possible combinations of certain letters in a word... Which is fine, except it now ends up as a list of tuples with too many quotes and commas.
import itertools
mainword = input(str("Enter a word: "))
n_word = int((len(mainword)))
outp = (list(itertools.permutations(mainword,n_word)))
What I want:
[yes, yse, eys, esy, sye, sey]
What I'm getting:
[('y', 'e', 's'), ('y', 's', 'e'), ('e', 'y', 's'), ('e', 's', 'y'), ('s', 'y', 'e'), ('s', 'e', 'y')]
Looks to me I just need to remove all the brackets, quotes, and commas.
I've tried:
def remove(old_list, val):
new_list = []
for items in old_list:
if items!=val:
new_list.append(items)
return new_list
print(new_list)
where I just run the function a few times. But it doesn't work.
You can recombine those tuples with a comprehension like:
Code:
new_list = [''.join(d) for d in old_list]
Test Code:
data = [
('y', 'e', 's'), ('y', 's', 'e'), ('e', 'y', 's'),
('e', 's', 'y'), ('s', 'y', 'e'), ('s', 'e', 'y')
]
data_new = [''.join(d) for d in data]
print(data_new)
Results:
['yes', 'yse', 'eys', 'esy', 'sye', 'sey']
You need to call str.join() on your string tuples in order to convert it back to a single string. Your code can be simplified with list comprehension as:
>>> from itertools import permutations
>>> word = 'yes'
>>> [''.join(w) for w in permutations(word)]
['yes', 'yse', 'eys', 'esy', 'sye', 'sey']
OR you may also use map() to get the desired result as:
>>> list(map(''.join, permutations(word)))
['yes', 'yse', 'eys', 'esy', 'sye', 'sey']
You can use the join function . Below code works perfect .
I am also attach the screenshot of the output.
import itertools
mainword = input(str("Enter a word: "))
n_word = int((len(mainword)))
outp = (list(itertools.permutations(mainword,n_word)))
for i in range(0,6):
outp[i]=''.join(outp[i])
print(outp)
This question is similar to Slicing a list into a list of sub-lists, but in my case I want to include the last element of each previous sub-list as the first element in the next sub-list. And I have to take into account that the last sub-list always has to have at least two elements.
For example:
list_ = ['a','b','c','d','e','f','g','h']
The result for a size 3 sub-list:
resultant_list = [['a','b','c'],['c','d','e'],['e','f','g'],['g','h']]
The list comprehension in the answer you linked is easily adapted to support overlapping chunks by simply shortening the "step" parameter passed to the range:
>>> list_ = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> n = 3 # group size
>>> m = 1 # overlap size
>>> [list_[i:i+n] for i in range(0, len(list_), n-m)]
[['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f', 'g'], ['g', 'h']]
Other visitors to this question mightn't have the luxury of working with an input list (slicable, known length, finite). Here is a generator-based solution that can work with arbitrary iterables:
from collections import deque
def chunks(iterable, chunk_size=3, overlap=0):
# we'll use a deque to hold the values because it automatically
# discards any extraneous elements if it grows too large
if chunk_size < 1:
raise Exception("chunk size too small")
if overlap >= chunk_size:
raise Exception("overlap too large")
queue = deque(maxlen=chunk_size)
it = iter(iterable)
i = 0
try:
# start by filling the queue with the first group
for i in range(chunk_size):
queue.append(next(it))
while True:
yield tuple(queue)
# after yielding a chunk, get enough elements for the next chunk
for i in range(chunk_size - overlap):
queue.append(next(it))
except StopIteration:
# if the iterator is exhausted, yield any remaining elements
i += overlap
if i > 0:
yield tuple(queue)[-i:]
Note: I've since released this implementation in wimpy.util.chunks. If you don't mind adding the dependency, you can pip install wimpy and use from wimpy import chunks rather than copy-pasting the code.
more_itertools has a windowing tool for overlapping iterables.
Given
import more_itertools as mit
iterable = list("abcdefgh")
iterable
# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Code
windows = list(mit.windowed(iterable, n=3, step=2))
windows
# [('a', 'b', 'c'), ('c', 'd', 'e'), ('e', 'f', 'g'), ('g', 'h', None)]
If required, you can drop the None fillvalue by filtering the windows:
[list(filter(None, w)) for w in windows]
# [['a', 'b', 'c'], ['c', 'd', 'e'], ['e', 'f', 'g'], ['g', 'h']]
See also more_itertools docs for details on more_itertools.windowed
Here's what I came up with:
l = [1, 2, 3, 4, 5, 6]
x = zip (l[:-1], l[1:])
for i in x:
print (i)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
(5, 6)
Zip accepts any number of iterables, there is also zip_longest
I have a list in my program: grid = []
The grid currently holds lines of strings in a format such as:
qwertyui
asdfghjk
zxcvbnml
I want to alter the list so that its format is changed to:
zaq
xsw
cde
vfr
bgt
nhy
mju
lki
So in a sense the list would just be turned 90 degrees clockwise. I also want to store the newly formatted strings in a different list called diff_grid[].
Use zip(), and keep in mind that it'll take the first element from each item, then the second, and so on.
>>> strings = ['qwertyui', 'asdfghjk', 'zxcvbnml']
>>> for item in zip(*(strings[::-1])):
... print(item)
...
('z', 'a', 'q')
('x', 's', 'w')
('c', 'd', 'e')
('v', 'f', 'r')
('b', 'g', 't')
('n', 'h', 'y')
('m', 'j', 'u')
('l', 'k', 'i')
If you wanted ('q', 'a', 'z') instead of ('z', 'a', 'q'), you wouldn't need the [::-1] that reverses the list of strings.
If you don't want to see the tuple structure in the output, you can use join() or unpack the tuple and use a custom end argument:
>>> for item in zip(*(strings[::-1])):
... print(*item, sep='')
...
zaq
xsw
cde
vfr
bgt
nhy
mju
lki
Assuming grid is a list of the strings you are referring to:
>>> grid = ["abc", "def", "xyz"]
Try
>>> diff_grid = [''.join(i) for i in zip(*grid[::-1])]
>>> diff_grid
['xda', 'yeb', 'zfc']
zip(*grid) will apply the zip operator on the strings of grid.
Note that you have to reverse grid (grid[::-1]) because of the order the zip operation is applied.