Related
I have this list:
new_list = ['a', '1', '--', '2', 'c', '3', 'd', '4', 'e' '5', 'f', '6', 'g', '7', 'h', '8', 'i']
It contains both numbers and words, however, the numbers are seen as strings and not integers.
I want to convert the numbers from strings to integers.
I tried with this myself:
for number in new_list:
if number.isalpha():
continue
else:
int(number)
It looks through the list and if it's something with letters it continues, however, it doesn't work when it seems "special characters" such as the two lines on the third element. I get an error message there.
I also tried this:
for number, element in enumerate(lista_lista):
if number.isalpha() == False:
int(number)
This only looks at every other element, which is a number, and uses isalpha(), and if that's False (which it should be), then I convert, but this doesn't work either.
Use number.isdigit() to recognize the numeric elements. Just because it's not alphabetic, it doesn't mean it's a number.
list_with_numers = [int(x) if x.isdigit() else x for x in new_list]
You can try this:
new_list = ['a', '1', '--', '2', 'c', '3', 'd', '4', 'e' '5', 'f', '6', 'g', '7', 'h', '8', 'i']
def to_int(x):
try:
return int(x)
except:
return x
[to_int(x) for x in new_list]
# Out[4]: ['a', 1, '--', 2, 'c', 3, 'd', 4, 'e5', 'f', 6, 'g', 7, 'h', 8, 'i']
This solution should be more performant than approaches like: int(x) if x.isdigit(), because you do not have to have call 2 different operations, like check if value is a digit and then apply the int conversion.
he below is a simple code without any error that you can use to fulfill your requirement, which is also easy to understand. Please have a check,
new_list = ['a','1','-','2','c','3','d','4','e','5','f','6','g','7','h','8','i']
for ind in range(len(new_list)):
if new_list[ind].isdigit():
new_list[ind]=int(new_list[ind])
else:
continue
print(new_list)
You can use str.isdigit and use list comprehension to modify like:
new_list = ['a', '1', '--', '2', 'c', '3', 'd', '4', 'e' '5', 'f', '6', 'g', '7', 'h', '8', 'i']
modified_list = [int(el) if el.isdigit() else el for el in new_list]
But it won't work for floats or negative integers in string form e.g. '-9', '11.5', if you need that you could do:
def convert_to_number(s):
try:
return int(s)
except:
try:
return float(s)
except:
return s
new_list = ['a', '1', '--', '2', 'c', '3', 'd', '4', 'e' '5', 'f', '6', 'g', '7', 'h', '8', 'i' ,'-9', '11.5']
print([convert_to_number(el) for el in new_list])
Output:
['a', 1, '--', 2, 'c', 3, 'd', 4, 'e5', 'f', 6, 'g', 7, 'h', 8, 'i', -9, 11.5]
Go for something like this, using list comprehension.
old_list = ['a', '1', '--', '2', 'c', '3', 'd', '4', 'e' '5', 'f', '6', 'g', '7', 'h', '8', 'i']
new_list = [int(character) if character.isdigit() else character for character in old_list]
output
['a', 1, '--', 2, 'c', 3, 'd', 4, 'e5', 'f', 6, 'g', 7, 'h', 8, 'i']
Let's analyze your code.
for number in new_list:
if number.isalpha():
continue
else:
int(number)
First of all, you iterate through new_list correctly. Now you also check if number is an alphabet that is correct. But you need to take action on that. Instead, you use continue. I suggest appending number to a list. Say it is not an alphabet, we try and turn number into an int. Sure, this works out. But your new_list will not change. Instead, you'd probably want to append number to a list. One problem I've spotted is, what if a character in the list is --. This is not an alphabet and not an integer. So by default, we will move to the else and try and perform int('--') which will return an error. So using .isdigit() is the best bet.
Use isdigit instead:
[int(x) if x.isdigit() else x for x in new_list]
I'm trying to generate an array of strings (or any other data structure that might be more useful for my task, but I can't think of anything else) in Python.
The program I'm working on has several sets of radio buttons. For example a set of "Block"/"Alternate" and "Single"/"Duplicate".
Examples on how the array of strings should look when they are activated:
Block, Single:
list = ['A', 'B', 'C', '1', '2', '3']
Alternating, Single:
list = ['A', '1', 'B', '2', 'C', '3']
Alternating, Duplicate:
list = ['A', 'A', '1', '1', 'B', 'B', '2', '2', 'C', 'C', '3', '3']
Those are only several examples, the program has way more, but the concept is the same.
I need to read this array of strings and use it as a schema of sorts to further select some data from my Pandas Dataframe.
How would I go about generating this array without writing an if clause for every single possible combination?
I tried to solve this using Jupyter Notebook and some widgets for the user interaction. I don' know how you get this informations but to replicate the same behaviour I am using this.
In [1]:
import ipywidgets as widgets # Widgets for user interactions
## Change the list as you want
my_list = ['A', 'B', 'C', '1', '2', '3']
single_duplicate = widgets.ToggleButtons(
description='Do you want to Duplicate the list ?',
options=['Single', 'Duplicate'],
value='Single',
style={'description_width': 'initial'}
)
single_duplicate
Out [1]:
In [2]:
block_alter = widgets.ToggleButtons(
description='Do you want to Alternate the list?',
options=['Block', 'Alternate'],
value='Block',
style={'description_width': 'initial'}
)
block_alter
Out [2]:
Then define the function to manipulate the list with the user input
In [3]:
def get_array(single_duplicate, block_alter, my_list):
temporary_list = []
## Answer to Single or Duplicate
if single_duplicate == 'Duplicate':
for elem in my_list:
temporary_list.append(elem)
temporary_list.append(elem)
else:
temporary_list = my_list
## Answer to Block or Aternate ?
new_list = []
if block_alter == 'Alternate':
half = int(len(temporary_list)/2)
for i in range(half):
new_list.append(temporary_list[i])
new_list.append(temporary_list[i + half])
else:
new_list = temporary_list
return new_list
Use get_array(single_duplicate.value, block_alter.value, my_list) to see the output with the user's choses
Here some exemples
In [3]:
print(get_array('Single', 'Block', my_list))
print(get_array('Duplicate', 'Block', my_list))
print(get_array('Single', 'Alternate', my_list))
print(get_array('Duplicate', 'Alternate', my_list))
Out [3]:
['A', 'B', 'C', '1', '2', '3']
['A', 'A', 'B', 'B', 'C', 'C', '1', '1', '2', '2', '3', '3']
['A', '1', 'B', '2', 'C', '3']
['A', '1', 'A', '1', 'B', '2', 'B', '2', 'C', '3', 'C', '3']
>>> import itertools
>>> a = ['1', '2', '3', '4', '5']
>>> b = ['a', 'b', 'c', 'd', 'e', 'f']
>>> list(itertools.chain.from_iterable(zip(a,b)))
['1', 'a', '2', 'b', '3', 'c', '4', 'd', '5', 'e']
As you can see, I have two asymmetrical list and I want to mix them like above. The problem is it ignore the last item.
Expected:
['1', 'a', '2', 'b', '3', 'c', '4', 'd', '5', 'e', 'f']
Actual:
['1', 'a', '2', 'b', '3', 'c', '4', 'd', '5', 'e']
Since you're using itertools in the first place, I assume you want this to work on any iterables, not just lists, and ideally without eagerly listifying them first. Otherwise, just do this:
list(itertools.chain.from_iterable(zip(a,b))) + a[len(b):] + b[len(a):]
The zip_longest function almost does what you want out of the box, but it inserts a fillvalue (default None) for each slot once the shorter iterable runs out. If your values are all truthy, you can just filter those out with if i as in Ajax1234's answer, or filter with None as the predicate, but if your values can be anything in Python, even None, the only way to do it gets pretty clunky:
_sentinel = object()
[elem for elem in itertools.chain.from_iterable(itertools.zip_longest(a, b, fillvalue=_sentinel))
if elem is not _sentinel]
But you can look at how zip_longest works and do the same thing yourself, only generating "incomplete" tuples instead of "filled-in" tuples, and then call it like this:
list(itertools.chain.from_iterable(zip_longest_nofill(a, b)))
Although making a variant of the zip_longest code from the docs that's easy enough to explain in an SO answer is a bit challenging, so maybe it's better to use an explicit loop:
def zip_longest_nofill(*args):
empty = object()
its = [iter(arg) for arg in args]
while True:
vals = (next(it, empty) for it in its)
tup = tuple(val for val in vals if val is not empty)
if not tup:
return
yield tup
I think this version is a lot easier to understand (although it was actually a bit harder to write…)
Of course if the only thing you're ever going to use zip_longest_nofill for is to implement your flattened_zip_nofill, it's even easier to just inline it into the flattening part, at which point you end up with basically the two-liner in the last section.
Instead of chain, use zip_longest:
import itertools
a = ['1', '2', '3', '4', '5']
b = ['a', 'b', 'c', 'd', 'e', 'f']
new_results = [i for b in itertools.zip_longest(a, b) for i in b if i is not None]
Output:
['1', 'a', '2', 'b', '3', 'c', '4', 'd', '5', 'e', 'f']
Just manually append the remaining:
def mix(a, b):
c = list(itertools.chain.from_iterable(zip(a,b)))
c += a[len(b)] + b[len(a):]
return c
One liner:
mix = lambda a, b: list(itertools.chain.from_iterable(zip(a,b))) + a[len(b)] + b[len(a):]
This should work but it's not very elegant
lst = []
for i in range(temp = max(len(a), len(b))):
if i < len(a): lst.append(a[i])
if i < len(b): lst.append(b[i])
lst
You can try itertools zip_longest:
a = ['1', '2', '3', '4', '5']
b = ['a', 'b', 'c', 'd', 'e', 'f']
import itertools
output=[]
for i in itertools.zip_longest(a,b):
if i[0]==None:
output.append(i[1])
else:
output.extend([i[0],i[1]])
print(output)
output:
['1', 'a', '2', 'b', '3', 'c', '4', 'd', '5', 'e', 'f']
How can I generate a random HTML colour (#ABABAB, etc) in Python? I tried doing something like
random.choice('0','1','2',)
etc. but it didn't work. Help? Thank you.
from random import choice
def colour():
hex_chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
randomColour = '#'
for i in range(0, 6):
randomColour = randomColour + choice(hex_chars)
return randomColour
I have the list:
list_mix = [['1','2','3'],['a','b','c'], ['d','e','f'], ['g','h','i']]
The first list must be merged with other lists in the list_mis. The result should be:
['1','2','3','a','b','c']
['1','2','3','d','e','f']
['1','2','3','g','h','i']
The following code gives me "TypeError: list indices must be integers, not list":
for item in list_mix[1:]:
print (list_mix[0] + list_mix[item])
Any solution without external libraries would be appreciated.
item is the sublist already, not an index. Just use it directly:
for item in list_mix[1:]:
print (list_mix[0] + item)
The Python for statement is a Foreach loop construct, assigning each element from list_mix[1:] to item in turn.
Demo:
>>> list_mix = [['1','2','3'],['a','b','c'], ['d','e','f'], ['g','h','i']]
>>> for item in list_mix[1:]:
... print (list_mix[0] + item)
...
['1', '2', '3', 'a', 'b', 'c']
['1', '2', '3', 'd', 'e', 'f']
['1', '2', '3', 'g', 'h', 'i']
Use a list comprehension add every sublist to sublist 0 of list_mix, use list_mix[1:] to start at the element after ['1','2','3'].
[list_mix[0] + x for x in list_mix[1:]]
[['1', '2', '3', 'a', 'b', 'c'], ['1', '2', '3', 'd', 'e', 'f'], ['1', '2', '3', 'g', 'h', 'i']]