Python question on join function getting different output - python

Why am I seeing this output while running this code:
list = []
for i in range(4):
l = int(input())
list.append(l)
print(str(list))
print("+".join(str(list)))
Output:
[1, 2, 3, 4]
[+1+,+ +2+,+ +3+,+ +4+]
Expected = [1+2+3+4]
Please correct my syntax

separator.join(sequence) inserts separator between each item in sequence; if sequence is a string, it simply sticks the separator in between every character of the string.
I think the root of your confusion is that you're converting the list into a string, when it seems like you really want to turn each item into a string (so that the list of strings can then be joined).
lst = [1, 2, 3, 4]
list_as_string = str(lst)
print(list_as_string)
=> "[1, 2, 3, 4]"
To make each item in the list a string, you can use a list comprehension. (List comprehensions are very useful Python tools for applying the same operation to each item in a sequence; if you haven't used them, check out this tutorial.)
list_of_strings = [str(i) for i in lst]
print(list_of_strings)
=> ["1", "2", "3", "4"]
The result of that can be joined like you would expect (and you can add brackets).
output = "[" + "+".join(list_of_strings) + "]"
print(output)
=> "[1+2+3+4]"
Alternatively, if for some reason you definitely want to convert the list to a string first, you can use the string.replace(old, new) method to simply replace every ", " with "+".
print(list_as_string.replace(", ", "+"))
=> "[1+2+3+4]"
Also note that list in Python is the actual name of the list class and it is a bad habit to redefine it as an ordinary variable.

You could use split(",") and "+".join().Also use .strip to remove the blank space.
Try this below:
print("+".join(map(str.strip, str(list).split(","))))
Result:
[1+2+3+4]

Related

Remove spaces from a list of integers

I wrote a code that accepts multiple numbers and converts them into a list of integers. But I get them with spaces.
For example: I enter as input: 1,2,3,4,5 (with commas).
I get a list of [1, 2, 3, 4, 5]
Now I just need to delete the spaces but It's not working, I need it to look something like this [1,2,3,4,5].
I tried doing it this way:
numbers = input().split(',')
for i in range(0, len(numbers)):
numbers[i] = int(numbers[i])
mylist = str(numbers).replace(' ','')
print(mylist)
This causes the square parentheses to be considered as items.
How do I delete the spaces the right way?
I think you are conflating the list and the representation of the list. The list itself doesn't have spaces, or even commas, it just has the items (in your case, the numbers). The representation of the list is just that - a way to represent the data inside of it in a normal, standard way. That standard includes commas and spaces.
If you want a new thing that represents the list and its items in the way you are saying, you can do that by making a new string just like that.
str(numbers).replace(' ','')
This has two functions in it, chained together. First, we do str(numbers) to get a string that is the string-representation of the list. This will be the string '[1, 2, 3, 4, 5]'. Then you replace any blank space-bar ' ' with nothing ''.
Edit:
I think I read your question too quickly and see that you did the exact same as what I have in my code here and said it isn't doing exactly what you want to do. I think the answer here is: no.
As I say in my first paragraph, there is the list and there is the lists representation. The function for the list's representation is a python built-in that can not be trivially overridden. I'm not saying it can't be done, but I don't think you'll get it done without defining some new things.
You can change the print behavior of the list to something you code yourself.
numbers = input().split(',')
for i in range(0, len(numbers)):
numbers[i] = int(numbers[i])
mylist = str(numbers).replace(' ','')
print('[' + ','.join([str(n) for n in numbers]) + ']')
This prints a bracket [, then each number separated by commas without any spaces, and finally the ending bracket ].
Output looks like this:
1, 2, 3, 4, 5
[1,2,3,4,5]
My understanding of your problem is that you want to input a list as a string and want to transform it into a Python list of numbers.
If you input the following string [1, 2, 3, 4, 5], then you can split on , . Then you need to consider removing the leftmost and rightmost character, that correspond to the brackets:
numbers = input()[1:-1].split(', ')
for i in range(len(numbers)):
numbers[i] = int(numbers[i])
print(numbers)
Other options to transform the numbers from strings to integers are the following:
Python built-in map function:
numbers = input()[1:-1].split(', ')
numbers = list(map(int, numbers))
print(numbers)
Python list comprehension:
numbers = input()[1:-1].split(', ')
numbers = [int(n) for n in numbers]
print(numbers)
What you might want to do is create a subclass of list that has the repr implementation you want. That way you can still operate on your list object as you would any other list (e.g. you can access numbers[0] and it will return the first number), but printing the list as a whole will produce the output you're looking for.
class MyList(list):
def __repr__(self) -> str:
return "[" + ",".join(repr(i) for i in self) + "]"
numbers = MyList(int(n) for n in input().split(","))
print(numbers)
print(numbers[0])
Input:
1,2,3,4,5
Output:
[1,2,3,4,5]
1
Since MyList is a list subclass, you can construct one from any iterable, including a generator expression (as in the code above) or an existing list, e.g.:
>>> n_copy = MyList(numbers)
>>> n_copy
[1,2,3,4,5]
You could use the re module's split function to deal with the whitespaces when splitting. Then you just need to join the elements with ',' and embed the whole thing between brackets in the string representation.
import re
numbers = re.split(r'\s*,\s*', input())
print(f"[{','.join(numbers)}]")

f-string syntax for unpacking a list with brace suppression

I have been examining some of my string format options using the new f-string format. I routinely need to unpack lists and other iterables of unknown length. Currently I use the following...
>>> a = [1, 'a', 3, 'b']
>>> ("unpack a list: " + " {} "*len(a)).format(*a)
'unpack a list: 1 a 3 b '
This, albeit a bit cumbersome, does the job using pre-3.6 .format notation.
The new f-string format option is interesting given runtime string concatenation. It is the replication of the number of {} that I am having problems with. In my previous example, I simply created the necessary structure and unpacked within the .format() section.
Attempts to do this yielded one variant that worked, however:
1) Both curly brackets together doesn't unpack...
>>> 'unpack a list' f' {{*a}}'
'unpack a list {*a}'
2) Adding spaces around the interior {} pair:
This works but leaves opening and closing braces {, } present:
>>> 'unpack a list' f' { {*a} }'
"unpack a list {1, 3, 'a', 'b'}"
2b) Concatenating the variants into one f-string
This made the look and syntax better, since the evaluation, apparently, is from left to right. This, however, still left the enclosing curly brackets present:
>>> f'unpack a list { {*a} }'
"unpack a list {1, 3, 'a', 'b'}"
3) Tried automatic unpacking with just {a}
Perhaps, I was overthinking the whole procedure and hoping for some form of automatic unpacking. This simply yielded the list representation with the curly brackets being replaced with [] :
>>> f'unpack a list {a}'
"unpack a list [1, 'a', 3, 'b']"
What is required to suppress the curly brackets in variant (2) above, or must I keep using the existing .format() method? I want to keep it simple and use the new capabilities offered by the f-string and not revert back beyond the python versions which pre-date what I am currently comfortable with. I am beginning to suspect that f'strings' do not offer a complete coverage of what is offered by its .format() sibling. I will leave it at that for now, since I haven't even ventured into the escape encoding and the inability to use \ in an f-string. I have read the PEP and search widely, however, I feel I am missing the obvious or what I wish for is currently not possible.
EDIT several hours later:
4) Use subscripting to manually slice off the brackets: str(a)[1:-2]
I did find this variant which will serve for some cases that I need
f'unpack a list: {str(a)[1:-2]}'
"unpack a list: 1, 'a', 3, 'b"
But the slicing is little more than a convenience and still leaves the string quotes around the resultant.
5) and the final solution from #SenhorLucas
a = np.arange(10)
print(f"{*a,}")
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
Unpacking with trailing comma.
Just add a comma after the unpacked list.
a = [1, 2, 3]
print(f"Unpacked list: {*a,}")
# Unpacked list: (1, 2, 3)
There is a longer explanation to this syntax in this thread.
Since any valid Python expression is allowed inside the braces in an f-string, you can simply use str.join() to produce the result you want:
>>> a = [1, 'a', 3, 'b']
>>> f'unpack a list: {" ".join(str(x) for x in a)}'
'unpack a list: 1 a 3 b'
You could of course also write a helper function, if your real-world use case makes the above more verbose than you'd like:
def unpack(s):
return " ".join(map(str, s)) # map(), just for kicks
>>> f'unpack a list: {unpack(a)}'
'unpack a list: 1 a 3 b'
Simple Python is probably more clear:
>>> 'unpack a list: ' + ' '.join(str(x) for x in a)
'unpack a list: 1 a 3 b'
With slicing:
>>> 'unpack a list: ' + ' '.join([str(x) for x in a][1:3])
'unpack a list: a 3'
I don't think that this is the way f-Strings are meant to be used. At best I can imagine preparing a print() compatible tuple, like:
mixed = [1, "list_string", 2]
number = 23
answer = 46
info = 'Content:', *mixed, f'{number} {answer}'
print(*info) # default sep=' '
Output
Content: 1 list_string 2 23 46
I made this a while back, to include commas Oxford style.
def unpack_list(lst): # Oxford comma
if not isinstance(lst, str):
lst = [str(item) for item in lst]
if len(lst) == 0:
return
if len(lst) == 1:
return ", ".join(lst)
if len(lst) == 2:
return ", and ".join(lst)
else:
first_part = lst[:-1]
last_part = lst[-1]
return ", ".join(first_part) + ", and " + last_part

I want to clean the element in a list. If my list contains number 1 ans a stirng "1" i want to keep only one element either integer or sting

l = [1,2,3,4,5,'1','2','3','4','nag','nag','venkat',5,6,7]
l1 = []
for i in l:
if (str(i) not in l1) and (i not in l1):
l1.append(i)
print l1
I want to clean my list. My list contains numbers and strings. In the above list l i have both 1 and "1". I want to remove either 1 or "1". I want the output as [1, 2, 3, 4, 5, "nag", "venkat", 6, 7]
Confirmed in IDLE that this provides the output you're looking for. Also, I updated the names of some of your variables to be a little easier to understand.
my_list = [1,2,3,4,5,'1','2','3','4','nag','nag','venkat',5,6,7]
output_list = []
for i in my_list:
try:
if (str(i) not in output_list) and (int(i) not in output_list):
output_list.append(i)
except ValueError:
if i not in output_list:
output_list.append(i)
print output_list
In Python it's common practice to use variables assuming that they're a certain type and just catch errors, instead of going through the process of checking the type (int, str, etc) on each one. Here, inside the try statement, I'm assuming the loop variable i is either an int or a str that contains only numbers. Provided that's the case, this section works fine.
However, we know that the list contains some strings of letters, so the try block will throw a ValueError. The except block catches that and, knowing that this error will result from an attempt to cast a string of letters as an int (when we use int(i)), we can now safely assume that the loop variable i refers to a string of letters, which we then check against the output_list and append if needed. I hope that helps.
There's a way with list comprehensions, you create a new list, but this example only works if you know what you want to remove:
l1 = [i for i in l if i != "1" if i != "2" if i != "3" if i != "4"]
#output
[1, 2, 3, 4, 5, 'nag', 'nag', 'venkat', 5, 6, 7]
or for example only removing the string "1" it would be
l1 = [i for i in l if i != "1"]
Maybe it could be implemented in a function and a loop to remove such elements with a single if statement with this way. Not sure, anyway I'd go with coralv's way.

How to print items within lists in a list

Hear me out, I do not simply want someone to solve this problem for me. I know it is not 100% complete yet, but currently when I run the program I get an error about "Can't convert 'list' object to str implicitly" I'm looking for help on how to fix this and why it is does this.
Here is the problem
Write code to print out each thing in the list of lists, L, with a '*' after it like
1*2*3*4*...8*a*b*c*d*
This requires knowing the print statement and using the end or sep argument option
Here is my list, sorry for not putting it in earlier
L = [[1,2,3,4],[5,6,7,8],['a','b','c','d']]
Here is my code at the moment
def ball(x): #random function name with one parameter
q = '' #
i = 0
if type(x) != list: #verifies input is a list
return"Error"
for i in x: #Looks at each variable in list
for j in i: #Goes into second layer of lists
q = q + j + '*'
print(q)
The reason for your error
"Can't convert 'list' object to str implicitly"
is that you're using the wrong variable in your nested for loops. Where you're concatenating values to your q variable, you mistakenly put q = q + i when you wanted q = q + j. You also will want to cast the value of j as a string so it can be concatenated with q. In order to get your desired output, you can simply add an asterisk into that statement - something like the following: q = q + str(j) + '*'. On a completely unrelated note, your else statement that just has "Mistake" in it should be removed completely - it doesn't follow an if and it doesn't actually return or assign to a variable.
Note that this is not the most elegant way to go about solving this problem. I agree with ilent2 that you should take a look at both list comprehension and the str.join() method.
If you have a list of strings,
myList = ['a', '123', 'another', 'and another']
You can join them using the str.join function:
Help on method_descriptor:
join(...)
S.join(iterable) -> string
Return a string which is the concatenation of the strings in the
iterable. The separator between elements is S.
myString = '#'.join(myList)
If your list contains mixed types or non-strings you need to convert each item to a string first:
anotherList = [1, 2, 'asdf', 'bwsg']
anotherString = '*'.join([str(s) for s in anotherList])
You might want to read about list comprehension or more about the join function. Note, the above doesn't print the output (unless you are using the interactive console), if you want the output to be printed you will need call print too
print myString
print anotherString
And, if you are working with lists-of-lists you may need to change how you convert each sub-list into a string (depending on your desired output):
myListList = [[1, 2, 3, 4], [2, 3, 6, 5], [6, 4, 3, 1]]
myOtherString = '#'.join(['*'.join([str(s) for s in a]) for a in myListList])
The last line is a little complicated to read, you might want to rewrite it as a nested for loop instead.

Python List Comprehension Setting Local Variable

I am having trouble with list comprehension in Python
Basically I have code that looks like this
output = []
for i, num in enumerate(test):
loss_ = do something
test_ = do something else
output.append(sum(loss_*test_)/float(sum(loss_)))
How can I write this using list comprehension such as:
[sum(loss_*test_)/float(sum(loss_))) for i, num in enumerate(test)]
however I don't know how to assign the values of loss_ and test_
You can use a nested list comprehension to define those values:
output = [sum(loss_*test_)/float(sum(loss_))
for loss_, test_ in ((do something, do something else)
for i, num in enumerate(test))]
Of course, whether that's any more readable is another question.
As Yaroslav mentioned in the comments, list comprehensions don't allow you to save a value into a variable directly.
However it allows you to use functions.
I've made a very basic example (because the sample you provided is incomplete to test), but it should show how you can still execute code in a list comprehension.
def loss():
print "loss"
return 1
def test():
print "test"
return 5
output = [loss()*test() for i in range(10) ]
print output
which is this case will result in a list [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
I hope this somehow shows how you could end up with the behaviour that you were looking for.
ip_list = string.split(" ") # split the string to a list using space seperator
for i in range(len(ip_list)): # len(ip_list) returns the number of items in the list - 4
# range(4) resolved to 0, 1, 2, 3
if (i % 2 == 0): ip_list[i] += "-" # if i is even number - concatenate hyphen to the current IP string
else: ip_list[i] += "," # otherwize concatenate comma
print("".join(ip_list)[:-1]) # "".join(ip_list) - join the list back to a string
# [:-1] trim the last character of the result (the extra comma)

Categories