How to create a list conditionally? - python

I have a following problem. I would like to form a list a conditionally.
Lets say I have a variable add_string and if it's True then
a = ["a","b","Added String","c"]
Else
a = ["a","b","c"]
what's the best way to do that? I can do that in the following manner
a = ["a","b","c"]
if add_string:
a.insert(2,"Added String")
But that's not ideal since list a might change in future and I will have to change the index in the insert function. Also I have a condition — this added string should always follow after "b". Another solution is to search for "b" in the list and then insert after that, but that adds complexity and it's ugly.
Ideally I thought it should be something like
a = ["a","b",if add_string then "Added String","c"]

a = ["a","b"] + (["Added String"] if add_string else []) + ["c"]

If you know all the values when you create a, you could do something like this:
add_string = True
a = ['a', 'b'] + (['Added String'] if add_string else []) + ['c']
Output:
['a', 'b', 'Added String', 'c']
If you don't know the values in a, you could use index to find the location of 'b' in a, and insert the string after that:
a = ["a","b","c"]
add_string = True
if add_string:
a.insert(a.index("b")+1,"Added String")
print(a)
Output:
['a', 'b', 'Added String', 'c']

You could set unwanted values to a known value (such as None) and then remove them using list comprehension:
add_string = False # Could be True
unfiltered_list = ["a","b","Added String" if add_string else None,"c"]
a = [x for x in unfiltered_list if x is not None]
print(a)

Related

python replace two list data from another list

In python in one variable i am getting list like :
stop_address_type = ['1','2']
and in another variable i am getting like :
stop_facility_name = ['A','B']
Result : this is what i actually want
stop_address_type = ['1','2']
stop_facility_name = ['','B']
another situation like :
stop_address_type = ['2','1']
stop_facility_name = ['A','']
what i actually want is when i ll get the 1 value in stop_address_type variable i want to blank the same value of list stop_facility_name like :
Here is a possible solution:
stop_facility_name = [n if t != '1' else ''
for n, t in zip(stop_facility_name, stop_address_type)]
This works with any number of '1's in your stop_address_type list.
You could get the index of '1' in stop_address_type using the index() method and then fill stop_facility_name with a blank:
i = stop_address_type.index('1')
stop_facility_name[i] = ''
print(stop_facility_name)
With stop_address_type = ['1','2'] and stop_facility_name = ['A','B'] you will get the following output:
['', 'B']
Please note that this will only work if there is only one occurrence of '1' in stop_address_type.
If you have more than one occurrence of '1' in stop_address_type, you could use list comprehension to get all the indices of the '1' occurrence and fill the corresponding values in stop_facility_name with a simple for loop:
stop_address_type = ['1','2','1']
stop_facility_name = ['A','B', 'C']
indices = [i for i in range(len(stop_address_type)) if stop_address_type[i] == '1']
for i in indices:
stop_facility_name[i] = ''
print(stop_facility_name)
This will produce the following output:
['', 'B', '']
You could pass the lists through a method like this:
stop_address_type = ['1', '2']
stop_facility_name = ['A', 'B']
def check_facility_name(address_typ_list, facility_name_list):
for i, obj in enumerate(address_typ_list):
if obj == '1':
facility_name_list[i] = ""
print(stop_facility_name)
# ['A', 'B']
check_facility_name(stop_address_type, stop_facility_name)
print(stop_facility_name)
# ['', 'B']
This will give you the desired output no matter where the 1 occurs in the adress_type_list
If you want to use the first value in stop_address_type as an index into stop_facility_name, you can do it like this:
stop_facility_name[int(stop_address_type[0])] = ''

Simple python string concatenation

I have following test,
def test_strings_concatenation(self):
dict = ['a', 'b', 'c']
dict_as_string = " ".join(dict)
expected = 'a b c'
assert dict_as_string is expected
and I want to get dict exactly, (identical to) expected. Is there any way to get this?
To begin with, never use pre-defined constants like dict as variable names as #Amadan pointed out, also ['a', 'b', 'c'] is a list, and not a dictionary, (which is a container to hold key-value pairs e.g. {"a":"b"}.
Also you would want to check for == since you want the list to be concatenated to a string, and not is, since is checks if two object refers to the same location of memory as #TomaszBartkowiak pointed out , like below
In [21]: a = 1
In [22]: b = a
In [23]: a is b
Out[23]: True
In [24]: li = ['a', 'b', 'c']
In [25]: s = ' '.join(li)
In [26]: s is li
Out[26]: False
Hence the code will change to
def test_strings_concatenation():
#Define list and concatenate it
li = ['a', 'b', 'c']
li_as_string = " ".join(li)
expected = 'a b c'
#Check for string equality
assert li_as_string == expected
test_strings_concatenation()

How do I replace characters in lists using dictionary in python

I want to write a code that will replace certain characters in a list in an efficient way using a dictionary.
If I have:
key = {'a':'z','b':'y','c':'x'}
List = ['a','b','c']
How can I get the output
zyx
edit to clarify. The output I want is really
randomvariableorsomething = ['z', 'y', 'x']
My apologies.
Will [key[x] for x in List] work if I don't have a key for it in the dict?
Use get and join:
>>> ''.join(key.get(e,'') for e in List)
'zyx'
If by 'replace' you mean to change the list to the values of the dict in the order of the elements of the original list, you can do:
>>> List[:]=[key.get(e,'') for e in List]
>>> List
['z', 'y', 'x']
key = {'a':'z','b':'y','c':'x'}
List = ['a','b','c']
print([key.get(x,"No_key") for x in List])
#### Output ####
['z', 'y', 'x']
If your interest is only to print them as string,then:
print(*[key.get(x,"No_key") for x in List],sep="")
#### Output ####
zxy
Just in case you need the solution without join.
ss = ''
def fun_str(x):
global ss
ss = ss + x
return(ss)
print([fun_str(x) for x in List][-1])
#### Output ####
zxy
Both keys and List are words in python that can collide with existing objects or methods (dict.keys() and List objects), so I replaced them with k and lst respectively for best practice:
[k[x] for x in lst]

How to check if a list is part of another list in Python

I have the following lists:
first=['a','b','c']
second=['a','a']
third=['a','b']
Is there way to compare second to first so I get FALSE,and TRUE for comparing third to first? I tried using sets but set(second).issubset(first) returns True, which is not what I need.
first=['a','b','c']
second=['a','a']
third=['a','b']
def sub_set(lst1, lst2):
tmp = lst2[:]
for i in lst1:
if i in tmp:
tmp.remove(i)
else:
return False
return True
print sub_set(second, first)
print sub_set(third, first)
output
False
True
if the order matters and the elements need to be sequential you could convert the list to a string (with join) and use this:
first=['a','b','c']
second=['a','a']
third=['a','b']
def is_sublist(sublist, reflist):
return ''.join(sublist) in ''.join(reflist)
print(is_sublist(sublist=second, reflist=first))
print(is_sublist(sublist=third, reflist=first))
You can make a comparison using slicing:
>>> first = ['a', 'b', 'c']
>>> second = ['a', 'a']
>>> third = ['a', 'b']
>>> second == first[:len(second)]
False
>>> third == first[:len(third)]
True
If order doesn't matter, you can use a count dictionary:
diffs = {a : second.count(a) - first.count(a) for a in second}
diffs_list = list(diffs1.values())
is_subset = len(diffs_list) == diffs_list.count(0)
That returns True for third, and False for second.
This simply counts the occurrence of each element of the subset in the superset, computes the difference of each count, then verifies that all differences are 0.

Python: Append double items to new array

lets say I have an array "array_1" with these items:
A b A c
I want to get a new array "array_2" which looks like this:
b A c A
I tried this:
array_1 = ['A','b','A','c' ]
array_2 = []
for item in array_1:
if array_1[array_1.index(item)] == array_1[array_1.index(item)].upper():
array_2.append(array_1[array_1.index(item)+1]+array_1[array_1.index(item)])
The problem: The result looks like this:
b A b A
Does anyone know how to fix this? This would be really great!
Thanks, Nico.
It's because you have 2 'A' in your array. In both case for the 'A',
array_1[array_1.index(item)+1
will equal 'b' because the index method return the first index of 'A'.
To correct this behavior; i suggest to use an integer you increment for each item. In that cas you'll retrieve the n-th item of the array and your program wont return twice the same 'A'.
Responding to your comment, let's take back your code and add the integer:
array_1 = ['A','b','A','c' ]
array_2 = []
i = 0
for item in array_1:
if array_1[i] == array_1[i].upper():
array_2.append(array_1[i+1]+array_1[i])
i = i + 1
In that case, it works but be careful, you need to add an if statement in the case the last item of your array is an 'A' for example => array_1[i+1] won't exist.
I think that simple flat list is the wrong data structure for the job if each lower case letter is paired with the consecutive upper case letter. If would turn it into a list of two-tuples i.e.:
['A', 'b', 'A', 'c'] becomes [('A', 'b'), ('A', 'c')]
Then if you are looping through the items in the list:
for item in list:
print(item[0]) # prints 'A'
print(item[1]) # prints 'b' (for first item)
To do this:
input_list = ['A', 'b', 'A', 'c']
output_list = []
i = 0;
while i < len(input_list):
output_list.append((input_list[i], input_list[i+1]))
i = i + 2;
Then you can swap the order of the upper case letters and the lower case letters really easily using a list comprehension:
swapped = [(item[1], item[0]) for item in list)]
Edit:
As you might have more than one lower case letter for each upper case letter you could use a list for each group, and then have a list of these groups.
def group_items(input_list):
output_list = []
current_group = []
while not empty(input_list):
current_item = input_list.pop(0)
if current_item == current_item.upper():
# Upper case letter, so start a new group
output_list.append(current_group)
current_group = []
current_group.append(current_item)
Then you can reverse each of the internal lists really easily:
[reversed(group) for group in group_items(input_list)]
According to your last comment, you can get what you want using this
array_1 = "SMITH Mike SMITH Judy".split()
surnames = array_1[1::2]
names = array_1[0::2]
print array_1
array_1[0::2] = surnames
array_1[1::2] = names
print array_1
You get:
['SMITH', 'Mike', 'SMITH', 'Judy']
['Mike', 'SMITH', 'Judy', 'SMITH']
If I understood your question correctly, then you can do this:
It will work for any length of array.
array_1 = ['A','b','A','c' ]
array_2 = []
for index,itm in enumerate(array_1):
if index % 2 == 0:
array_2.append(array_1[index+1])
array_2.append(array_1[index])
print array_2
Output:
['b', 'A', 'c', 'A']

Categories

Resources