Replace multiple elements in a list with a single element - python-3.x

I want to replace two or more elements with a single element in a list like this:
mylist=['a','b','c']
Now I want to replace 'a' and 'b' elements with another element 'z'.
So output should be:
['z','z','c']

a list-comprehension an option:
mylist = ['a', 'b', 'c']
new_list = [x if x not in "ab" else "z" for x in mylist]
print(new_list) # ['z', 'z', 'c']
if the elements you want to replace are more complicated you could try:
if x not in {"a", "b"}
if you want to change things based on the index i you can use enumerate:
new_list = [x if i >= 2 else "z" for i, x in enumerate(mylist)]
print(new_list) # ['z', 'z', 'c']
but then you could consider slicing:
new_list = 2 * ["z"] + mylist[2:]

Related

How to find the combination of a list to a list without rearrangement?

I am want to achieve all possible combinations (w/o rearr.) of partitioning/breaking the string by k elements.
for example,
I have a string "abcd" and k=3, I want achieve the following,
if [a,b,c,d] and k=3 then return,
[ [ [a], [b], [c,d] ]
[ [a], [b,c], [d] ]
[ [a,b], [c], [d] ] ]
for example,
I have a string "abcde" and k=3, I want achieve the following,
if [a,b,c,d,e] and k=3 then return,
[ [ [a], [b], [c,d,e] ]
[ [a], [b,c,d], [e] ]
[ [a,b,c], [d], [e] ]
[ [a], [b,c], [d,e] ]
[ [a,b], [c], [d,e] ]
[ [a,b], [c,d], [e] ] ]
Note, that all the combinations have the a-b-c-d(-e) are in straight order i.e. without rearrangement.
Let's say there's a function "breaklist" which does the work, takes the list and breaks it into k elements of the combination of the elements in the list (w/o rearr.) and finally, returns me a three-dimensional array.
def breakList(l: list, k: int):
...
return partitionedList
My Logic:
Let's say the size of the string be, "z=len(string)" and "k" be an integer by which the string is to be divided.
Now by observation, the maximum size of a element of the combination is "z-k+1", let that be n.
Now start from the first index, go till "n" and the rest by "j=1" then saves in a 3D Array.
Next iteration, will be the same by decrement of n by 1 i.e. "n-1" and the rest by "j=2" then saves to the 3D Array.
Next iteration, will decrement n by another 1 i.e. "(n-1)-1" and the rest by "j=3" then saves to the 3D Array.
"j" runs till "n", and, "n" runs to 1
This gives all the combination w/o rearrangement.
But this is not the most efficient approach I came up with, and at the same time it makes the task somewhat complex and time-consuming.
So, is there any better approach (I know there is...)? and also can I simplify the code (in terms of number of lines of codes) by using python3?
There's a better way... As mentioned in the referenced question, you just need to re-focus your thinking on the slice points. If you want 3 segments, you need 2 partitions. These partitions are all of the possible combinations of index positions between [1, end-1]. Sounds like a job for itertools.combinations!
This is only a couple lines of code, with the most complicated piece being the printout, and if you don't need to print, it gets easier.
from itertools import combinations as c
data = list('abcdefg')
k = 3
slice_point_sets = c(range(1, len(data)), k-1)
# do the slicing
for point_set in slice_point_sets:
start = 0
for end in point_set:
print(data[start:end], end=',')
start = end
print(data[end:])
# or pop it into a 3d array...
slice_point_sets = c(range(1, len(data)), k-1)
result = []
for point_set in slice_point_sets:
sublist = []
start = 0
for end in point_set:
sublist.append(data[start:end])
start = end
sublist.append(data[end:])
result.append(sublist)
Output:
['a'],['b'],['c', 'd', 'e', 'f', 'g']
['a'],['b', 'c'],['d', 'e', 'f', 'g']
['a'],['b', 'c', 'd'],['e', 'f', 'g']
['a'],['b', 'c', 'd', 'e'],['f', 'g']
['a'],['b', 'c', 'd', 'e', 'f'],['g']
['a', 'b'],['c'],['d', 'e', 'f', 'g']
['a', 'b'],['c', 'd'],['e', 'f', 'g']
['a', 'b'],['c', 'd', 'e'],['f', 'g']
['a', 'b'],['c', 'd', 'e', 'f'],['g']
['a', 'b', 'c'],['d'],['e', 'f', 'g']
['a', 'b', 'c'],['d', 'e'],['f', 'g']
['a', 'b', 'c'],['d', 'e', 'f'],['g']
['a', 'b', 'c', 'd'],['e'],['f', 'g']
['a', 'b', 'c', 'd'],['e', 'f'],['g']
['a', 'b', 'c', 'd', 'e'],['f'],['g']
I think this could work:
Get all possible sum partitions of the len(your_list).
Filter them by len(partition) == k.
Get the itertools.permutations by k elements of all this partitions.
Now you have list of lists like this: [(1, 1, 2), (1, 2, 1), (1, 1, 2), (1, 2, 1), (2, 1, 1), (2, 1, 1)]
Clean up this list of duplicates (make the set):
{(1, 2, 1), (2, 1, 1), (1, 1, 2)}
For each permutation pick exact number elements from your_list:
(1, 1, 2) -> [[a], [b], [c, d]],
(1, 2, 1) -> [[a], [b, c], [d]],
and so on..
Code
import itertools as it
start_list = ['a', 'b', 'c', 'd', 'e']
k = 3
def partitions(n, k=None): # step 1 function
if k is None:
k = n
if n == 0:
return []
return ([[n]] if n<=k else []) + [
l + [i]
for i in range(1, 1+min(n, k))
for l in partitions(n-i, i)]
final_list = []
partitions = filter(lambda x: len(x)==k, partitions(len(start_list))) # step 1-2
for partition in partitions:
pickings = set(it.permutations(partition, k)) # step 3-5
for picking in pickings:
temp = []
i = 0
for e in picking: # step 6
temp.append(start_list[i:i+e])
i += e
final_list.append(temp)
print(*final_list, sep='\n')

Python3 sort a list based on another list when the lists are uneven in length

I have two lists:
list1 = ["a","e","d","c","f","g"]
list2 = ["a","c","d","f"]
In this the list1 cannot be sorted and should be retained as is. I am trying to sort the list2 exactly in the same order as list1 and get the missing values from list1 that exists between the first and last value of list2.
For example, if I sort list2 as according to list1using the following code,
list2 = [x for _, x in sorted(zip(list1,list2))]
I get the following index based sorted list:
list2 = ['a', 'f', 'd', 'c']
However the desired output is
list2 = ['a','d','c','f']
How can I sort the list2 according to the list1 taking the literal sequence of elements and not the index position based sorting.
It might not be the most efficient, and it doesn't cope with duplicates, but the following list comprehension should do what you want:
list1 = ["a","e","d","c","f","g"]
list2 = ["a","c","d","f"]
print([x for x in list1 if x in list2])
['a', 'd', 'c', 'f']
It walks list1, using the item if it is found in list2.

How to create a dictionary using the the list of letters as keys with values being the uppercase version of the letters

How to create a dictionary using the list of letters as keys with values being the uppercase version of the letters.
Using a dict comprehension with all of your chosen letters will give you key:value pairs with 'lower':'UPPER'.
lower_to_upper = {
letter: letter.upper()
for letter in 'abcdefghijklmnopqrstuvwxyz'
}
Use a list comprehension to build tuples that are input to create the dictionary.
mylist = ['a', 'b', 'c']
dict((i, i.upper()) for i in mylist)
output
{'a': 'A', 'b': 'B', 'c': 'C'}

I need to convert a single input string into a dictionary

I need to convert a single input string into a dictionary with its place indices as keys and the letters as values in python. But I'm stuck here. Any help will be appreciated.
r = list("abcdef")
print (r)
for index,char in enumerate(r,0):
indd = str(index)
print(indd)
abc = indd.split(",")
list2 = list(abc)
d = dict(zip(list2,r))
print(d)
This is one approach using range.
Demo:
r = list("abcdef")
d = {}
for i in range(len(r)):
d[i] = r[i]
print(d)
Output:
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}
Or a simpler approach using dict().
r = list("abcdef")
d = dict(zip(range(len(r)), r))
print(d)
You have a string abcdef.
First make a list of tuples having first element of tuple as place index and second element of the tuple as the letter at that index. This can be done in this way:
tuples = list(enumerate("abcdef"))
Now, using the dictionary constructor, convert this list of tuples to a dictionary as given below:
dict(tuples)
Demo:
>>> dict(list(enumerate("abcdef")))
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f'}

Tuples screwing with me

I'm trying to append everything but 'A' from tuple into new_tuple
>>> tuple=('A', 'B', 'C', 'D')
>>> for i in tuple:
new_tuple=()
if i!='A':
new_tuple+=(i,)
>>> new_tuple
('D',)
It only prints ('D',) instead of ('B','C','D')
But it's funny how you can loop through every element and print it....
>>> for i in tuple:
print (i)
A
B
C
D
You reinitialize new_tuple through each iteration. Put new_tuple=() before the loop and it should work.
tuple = ('A', 'B', 'C', 'D')
new_tuple = ()
for i in tuple:
if i != 'A':
new_tuple += (i,)
print new_tuple

Resources