I am trying to convert a line from a text file into a list. The contents of the test file are:
1 2 3 4 f g
I have read the contents into a list lst = ['1','2','3','4','f','g']. I want to remove 'f' and 'g' (or whatever characters they may be) and convert all the remaining elements to int type. How can I achieve this?
Instead of removing, rather build a new list. Python is more efficient when just appending items to a list. Here we try to convert i to an int - if it is convertable then it reads as some base-10 number, with possible + or - sign. If it does not match, then int(i) throws a ValueError exception which we just ignore. Those values that were correctly converted will be appended to a new result list.
result = []
for i in elements:
try:
result.append(int(i))
except ValueError:
pass
This is a good time for a list comprehension. Convert to int only if isnumeric()
arr = [int(x) for x in arr if x.isnumeric()]
Try checking if each character can be converted into a character:
arr = ['1', '2', '3', '4', 'f', 'g']
for c, char in enuemrate(arr[:]):
try:
arr[c] = int(char)
except ValueError:
del arr[c]
print(arr)
You can use the built-in Python method isalpha().
The method returns “True” if all characters in the string are alphabets, Otherwise, it returns “False”.
I'm assuming that there are no alpha-numeric elements in your list, and your list contains either digits or alphabets. You could try something like this:
elements = [1, 2, 3, 4, 'f', 'g']
for element in elements:
if element.isalpha():
elements.remove(element) #Removing the alphabets
#Converting the remaining elements to int
elements = [ int(x) for x in elements ]
Related
This question already has answers here:
Get a list of numbers as input from the user
(11 answers)
Convert all strings in a list to int
(10 answers)
Closed last month.
l = list(input('enter a list:'))
print(l)
In this program 'l' is the variable which will take input from the user and return it as a list.
But when 'l' is printed it returns the integer as a string.
Output:
enter a list: 12345
['1', '2', '3', '4', '5']
Process finished with exit code 0
What is the problem with this code?
You can call int() to convert the characters to integers.
l = list(map(int, input("Enter a list:")))
print(l)
If you enter 12345 this will print [1, 2, 3, 4, 5]
When you input 12345, you're inputting a string - not an integer.
When you convert a string to a list the list will be comprised of the string's constituent parts - i.e., all of its characters.
You're asking the user to 'enter a list' and that's exactly what's happening - a list of characters
All input is inputted as a string, and it's up to you to cast/convert it to a different type if you need it. If you know the input is a string of digit, you can treat it as an iterable and explicitly convert every character to a digit:
mylist = [int(i) for i in input('Enter a series of digits: ')]
If you want to create a list of integers from the user's input, you can use a list comprehension or for loop to convert each character to an integer, something like this-
l = [int(i) for i in input('Give input:')]
print(l)
Why your solution is not working: In Python, the input function returns a string, which is a sequence of characters. When you pass the string to the list function, it creates a list of the individual characters in the string. For example, if you enter the string "12345", the list will be ['1', '2', '3', '4', '5'].
This question already has answers here:
Access multiple elements of list knowing their index [duplicate]
(11 answers)
Closed 12 months ago.
So i want to take any integer as an input and get an output based on arrays like this:
Input: 012346
array = ["a","b","c","d","e","f","g"]
Output: abcdeg
how would i do that?
Use a comprehension. Convert input string to a list of characters then get the right element from array:
inp = '012346'
# For inp to be a string in the case of inp is an integer
out = ''.join([array[int(i)] for i in str(inp)])
print(out)
# Output
abcdeg
Update
How i would treat numbers above 10 since they would get broken down to 1 and 0
Suppose the following input:
inp = '1,10,2,3'
array = list('abcdefghijklmn')
out = ''.join([array[int(i)] for i in inp.split(',')])
print(out)
# Output
'bkcd'
Looks like operator.itemgetter could do the job.
>>> from operator import itemgetter
>>> itemgetter(0, 1, 2, 3, 4, 6)(array)
('a', 'b', 'c', 'd', 'e', 'g')
The input function in Python always returns a string, unless you cast it into another type. So you can loop over the digits of this string, cast the digits individually into an integer, and use that to fetch the letters from the list and concatenate them:
str = “”
data = input(“Data? “)
for digit in data:
str += array[int(digit)]
I have a list that looks like this:
json_file_list = ['349148424_20180312071059_20190402142033.json','349148424_20180312071059_20190405142033.json','360758678_20180529121334_20190402142033.json']
and a empty list:
list2 = []
What I want to do is compare the characters up until the second underscore '_', and if they are the same I only want to append the max of the full string, to the new list. In the case above, the first 2 entries are duplicates (until second underscore) so I want to base the max off the numbers after the second underscore. So the final list2 would have only 2 entries and not 3
I tried this:
for row in json_file_list:
if row[:24] == row[:24]:
list2.append(max(row))
else:
list2.append(row)
but that is just returning:
['s', 's', 's']
Final output should be:
['349148424_20180312071059_20190405142033.json','360758678_20180529121334_20190402142033.json']
Any ideas? I also realize this code is brittle with the way I am slicing it (what happens if the string gets longer/shorter) so I need to come up with a better way to do that. Maybe base if off the second underscore instead. The strings will always end with '.json'
I'd use a dictionary to do this:
from collections import defaultdict
d = defaultdict(list)
for x in json_file_list:
d[tuple(x.split("_")[:2])].append(x)
new_list = [max(x) for x in d.values()]
new_list
Output:
['349148424_20180312071059_20190405142033.json',
'360758678_20180529121334_20190402142033.json']
The if statement in this snippet:
for row in json_file_list:
if row[:24] == row[:24]:
list2.append(max(row))
else:
list2.append(row)
always resolves to True. Think about it, how could row[:24] be different from itself? Given that it's resolving to True, it's adding the farthest letter in the alphabet (and in your string), s in this case, to list2. That's why you're getting an output of ['s', 's', 's'].
Maybe I'm understanding your request incorrectly, but couldn't you just append all the elements of the row to a list and then remove duplicates?
for row in json_file_list:
for elem in row:
list2.append(elem)
list2 = sorted(list(set(list2)))
I suppose you can splice what you want to compare, and use the built in 'set', to perform your difference:
set([x[:24] for x in json_file_list])
set(['360758678_20180529121334', '349148424_20180312071059'])
It would be a simple matter of joining the remaining text later on
list2=[]
for unique in set([x[:24] for x in json_file_list]):
list2.append(unique + json_file_list[0][24:])
list2
['360758678_20180529121334_20190402142033.json',
'349148424_20180312071059_20190402142033.json']
I can't imagine I'm going to get much help from this due to my inability to explain it. But for instance I have a string like so:
s = "[1,[2,2,[3,4]],5]"
and I need to convert it into a nested list item as such
lst = ["1",["2","2",["3","4"]],"5"]
that if I were to go lst[1][2][0] it would return '3'.
The way I have tried to do it was by creating a substring for every number within '[' and end of string characters and then slowly nest it back up
def ParseList(strlist):
if '[' in strlist:
print strlist
return ParseList(GetBetweenChar(strlist,'[',None))
else:
return strlist
however it returns:(which although maybe a good start? I dont know where to continue)
[1,[2,2,[3,4]],5]
1,[2,2,[3,4]],5
2,2,[3,4]],
3,4]]
which I would think I would append that to a list item but I dont know how to..
You can use ast.literal_eval to safely convert the string to a nested list of integers. Then define a nested map function to convert to all elements to strings, whilst maintaining the nesting structure.
from ast import literal_eval
s = "[1,[2,2,[3,4]],5]"
ls = literal_eval(s)
# yes I know there is something else called nmap
def nmap(fn, iterable):
res = []
for i in iterable:
if isinstance(i, list): # could be tuple or something else?
res.append(nmap(fn, i))
else:
res.append(fn(i))
return res
result = nmap(str, ls)
print(result)
print(result[1][2][0])
result:
['1', ['2', '2', ['3', '4']], '5']
3
You can use eval(). Just be careful to make sure the string is safe because eval will convert a string to valid python code.
>>> eval("[1,[2,2,[3,4]],5]")[1][2][0]
3
Some more info: What does Python's eval() do?
If you didn't require every piece to be a string, but you could let numbers be numbers, then you can use the json library:
>>> s = "[1,[2,2,[3,4]],5]"
>>> import json
>>> json.loads(s)
[1, [2, 2, [3, 4]], 5]
Notice that if your original list contains numbers or booleans, they will stay as numbers or booleans. This is probably what you want, BUT if you really need everything to be strings, then you can recurse through the nested arrays and apply str to everything (look for "How to do flatmap in Python") or request further help in the comment section below.
You could proceed by first adding the quotes around the digits, then eval the list:
s = "[1,[2,2,[3,4]],5]"
res = ''
for c in s:
if c.isdigit():
res += '"' + c + '"'
else:
res += c
s = eval(res)
s
output:
['1', ['2', '2', ['3', '4']], '5']
This will work for single digit numbers; a little bit more work would be needed for multiple digits, or floats
Eval is not safe for user input.
You can do something like for python (2.6+):
>>> import ast
>>> s = "[1,[2,2,[3,4]],5]"
>>> lst = ast.literal_eval(s)
>>> str(lst[1][2][0])
'3'
I have no clue about Python and started to use it on some files. I managed to find out how to do all the things that I need, except for 2 things.
1st
>>>line = ['0', '1', '2', '3', '4', '5', '6']
>>>#prints all elements of line as expected
>>>print string.join(line)
0 1 2 3 4 5 6
>>>#prints the first two elements as expected
>>>print string.join(line[0:2])
0 1
>>>#expected to print the first, second, fourth and sixth element;
>>>#Raises an exception instead
>>>print string.join(line[0:2:4:6])
SyntaxError: invalid syntax
I want this to work similar to awk '{ print $1 $2 $5 $7 }'. How can I accomplish this?
2nd
how can I delete the last character of the line? There is an additional ' that I don't need.
Provided the join here is just to have a nice string to print or store as result (with a coma as separator, in the OP example it would have been whatever was in string).
line = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
print ','.join (line[0:2])
A,B
print ','.join (line[i] for i in [0,1,2,4,5,6])
A,B,C,E,F,G
What you are doing in both cases is extracting a sublist from the initial list. The first one use a slice, the second one use a list comprehension. As others said you could also have accessed to elements one by one, the above syntaxes are merely shorthands for:
print ','.join ([line[0], line[1]])
A,B
print ','.join ([line[0], line[1], line[2], line[4], line[5], line[6]])
A,B,C,E,F,G
I believe some short tutorial on list slices could be helpfull:
l[x:y] is a 'slice' of list l. It will get all elements between position x (included) and position y (excluded). Positions starts at 0. If y is out of list or missing, it will include all list until the end. If you use negative numbers you count from the end of the list. You can also use a third parameter like in l[x:y:step] if you want to 'jump over' some items (not take them in the slice) with a regular interval.
Some examples:
l = range(1, 100) # create a list of 99 integers from 1 to 99
l[:] # resulting slice is a copy of the list
l[0:] # another way to get a copy of the list
l[0:99] # as we know the number of items, we could also do that
l[0:0] # a new empty list (remember y is excluded]
l[0:1] # a new list that contains only the first item of the old list
l[0:2] # a new list that contains only the first two items of the old list
l[0:-1] # a new list that contains all the items of the old list, except the last
l[0:len(l)-1] # same as above but less clear
l[0:-2] # a new list that contains all the items of the old list, except the last two
l[0:len(l)-2] # same as above but less clear
l[1:-1] # a new list with first and last item of the original list removed
l[-2:] # a list that contains the last two items of the original list
l[0::2] # odd numbers
l[1::2] # even numbers
l[2::3] # multiples of 3
If rules to get items are more complex, you'll use a list comprehension instead of a slice, but it's another subjet. That's what I use in my second join example.
You don't want to use join for that. If you just want to print some bits of a list, then specify the ones you want directly:
print '%s %s %s %s' % (line[0], line[1], line[4], line[6])
Assuming that the line variable should contain a line of cells, separated by commas...
You can use map for that:
line = "1,2,3,4,5,6"
cells = line.split(",")
indices=[0,1,4,6]
selected_elements = map( lambda i: cells[i], indices )
print ",".join(selected_elements)
The map function will do the on-the-fly function for each of the indices in the list argument. (Reorder to your liking)
You could use the following using list comprehension :
indices = [0,1,4,6]
Ipadd = string.join([line[i] for i in xrange(len(line)) if i in indices])
Note : You could also use :
Ipadd = string.join([line[i] for i in indices])
but you will need a sorted list of indices without repetition of course.
Answer to the second question:
If your string is contained in myLine, just do:
myLline = myLine[:-1]
to remove the last character.
Or you could also use rstrip():
myLine = myLine.rstrip("'")
>>> token = ':'
>>> s = '1:2:3:4:5:6:7:8:9:10'
>>> sp = s.split(token)
>>> token.join(filter(bool, map(lambda i: i in [0,2,4,6] and sp[i] or False, range(len(sp)))))
'1:3:5:7'
l = []
l.extend(line[0:2])
l.append(line[5]) # fourth field
l.append(line[7]) # sixth field
string.join(l)
Alternatively
"{l[0]} {l[1]} {l[4]} {l[5]}".format(l=line)
Please see PEP 3101 and stop using the % operator for string formatting.