I am trying to use the number of items inside of a list that is inside of another list to make a bar chart, however, when I try to count the length of each individual list inside of that list, i get NameError: name 'no' is not defined
mesasnovio = [[no,nope,yes],[a,b,c,d],[f,g,h,i],[j,k,l,m],[s,t]]
print (len(mesasnovio[1]))
I want it to be able to show me the length
>>> 3
You missed ''.
mesasnovio = [['no','nope','yes'],['a','b','c','d'],['f','g','h','i'],['j','k','l','m'],['s','t']]
print (len(mesasnovio[1]))
Also, because lists are zero-indexed in Python, mesasnovio[1] refers to ['a', 'b', 'c', 'd']. So you will get a length of 4, not 3.
Here is one way using map to get all len of list inside your list
lenl=list(map(len,mesasnovio))
lenl
Out[595]: [3, 4, 4, 4, 2]
lenl[0]
3
You need to wrap all of your strings in quotations.
mesasnovio = [['no','nope','yes'],['a','b','c','d'],['f','g','h','i'],['j','k','l','m'],['s','t']]
Others have addressed your issue with not encapsulating your strings, but if you would like the length of all inner lists
lengths = list(map(len, mesasnovio))
Related
This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 6 months ago.
I am trying to write simple code to print an item of a list and remove it after printing:
list = ['a', 'b', 'c']
for i in list:
print(i)
list.remove(i)
But output is weird:
a
c
Why is output thay way?
When you iterate over a list, you get the items in order of their indices (item 0, item 1, item 2, etc). When you remove an item from a list, the indices of all the items after that shift by one.
In the first iteration, the list is ['a', 'b', 'c'], and i is list[0].
During the first iteration, you remove 'a'.
In the second iteration, the list is ['b', 'c'], and i is list[1]. You get 'c' instead of 'b' because 'c' is now at index 1.
If you want to remove each item as you iterate, the better approach would be to iterate in a while loop as long as the list contains items, and pop as you print:
my_list = ['a', 'b', 'c']
while my_list:
print(my_list.pop(0))
In many cases, it's better to do the thing you want to do in the iteration, and then clear the list:
for i in my_list:
print(i)
my_list.clear()
You're currently iterating while removing the items, if you want alter the list while reading it then probably you want to use the length "as index":
list = ['a', 'b', 'c']
while len(list):
# pop does what you want: read the element at index [i] and remove it from the list
print(list.pop(0))
Output:
a
b
c
Explanation
the reason the output seems strange it's because you are removing items when iterating over a list.
the problem here is that python iterates checking for the index.
Consider this example:
lst = [32,43,2]
for x in lst:
lst.pop(0)
print(x,lst)
Outputs
32 [43, 2]
2 [2]
here you can see the problem. in the first iteration it took the first item that was removed, all ok. The problem starts with the second iteration.
The iterator thinks the index to go is 1 (2nd element) but it's actually the 1st since the first element was removed.
You can fix it also by iterating the reversed list as the index cannot change.
also see this question for more information
Possible solutions
You should iterate over a copy instead:
for x in mylist.copy():
mylist.remove(x)
You could also use a while loop and list.pop.
while mylist:
print(mylist.pop(0))
Advice
Before leaving, I would like to give some advice.
Don't use builtin as variable names, it causes confusion and could cause conflict in your code if it uses those builtin names.
I would advice to clear the list after the loop using the list.clear() method.
Use the list.pop method if you want to know a value and remove it at the same time.
Useful links
python datastructures official documentation
python list w3school
linuxhint python list methods
I encountered a snippet of code like the following:
array = ['a', 'b', 'c']
ids = [array.index(cls.lower()) for cls in array]
I'm confusing for two points:
what does [... for cls in array] mean, since cls is a reserved keyword for class, why not just using [... for s in array]?
why bother to write something complicated like this instead of just [i for i in range(len(array))].
I believe this code is written by someone more experienced with python than me, and I believe he must have some reason for doing so...
cls is not a reserved word for class. That would be a very poor choice of name by the language designer. Many programmers may use it by convention but it is no more reserved than the parameter name self.
If you use distinct upper and lower case characters in the list, you will see the difference:
array = ['a', 'b', 'c', 'B','A','c']
ids = [array.index(cls.lower()) for cls in array]
print(ids)
[0, 1, 2, 1, 0, 2]
The value at position 3 is 1 instead of 3 because the first occurrence of a lowercase 'B' is at index 1. Similarly, the value at the last positions is 2 instead of 5 because the first 'c' is at index 2.
This list comprehension requires that the array always contain a lowercase instance of every uppercase letter. For example ['a', 'B', 'c'] would make it crash. Hopefully there are other safeguards in the rest of the program to ensure that this requirement is always met.
A safer, and more efficient way to write this would be to build a dictionary of character positions before going through the array to get indexes. This would make the time complexity O(n) instead of O(n^2). It could also help make the process more robust.
array = ['a', 'b', 'c', 'B','A','c','Z']
firstchar = {c:-i for i,c in enumerate(array[::-1],1-len(array))}
ids = [firstchar.get(c.lower()) for c in array]
print(ids)
[0, 1, 2, 1, 0, 2, None]
The firstchar dictionary contains the first index in array containing a given letter. It is built by going backward through the array so that the smallest index remains when there are multiple occurrences of the same letter.
{'Z': 6, 'c': 2, 'A': 4, 'B': 3, 'b': 1, 'a': 0}
Then, going through the array to form ids, each character finds the corresponding index in O(1) time by using the dictionary.
Using the .get() method allows the list comprehension to survive an upper case letter without a corresponding lowercase value in the list. In this example it returns None but it could also be made to return the letter's index or the index of the first uppercase instance.
Some developers might be experienced, but actually terrible with the code they write and just "skate on by".
Having said that, your suggested output for question #2 would differ if the list contained two of any element. The suggested code would return the first indices where a list element occurs where as yours would give each individual items index. It would also differ if the array elements weren't lowercase.
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.
I was trying to write a piece of program that will remove any repeating items in the list, but I get a list index out of range
Here's the code:
a_list = [1, 4, 3, 2, 3]
def repeating(any_list):
list_item, comparable = any_list, any_list
for x in any_list:
list_item[x]
comparable[x]
if list_item == comparable:
any_list.remove(x)
print(any_list)
repeating(a_list)
So my question is, what's wrong?
Your code does not do what you think it does.
First you are creating additional references to the same list here:
list_item, comparable = any_list, any_list
list_item and comparable are just additional names to access the same list object.
You then loop over the values contained in any_list:
for x in any_list:
This assigns first 1, then 4, then 3, then 2, then 3 again to x.
Next, use those values as indexes into the other two references to the list, but ignore the result of those expressions:
list_item[x]
comparable[x]
This doesn't do anything, other than test if those indexes exist.
The following line then is always true:
if list_item == comparable:
because the two variables reference the same list object.
Because that is always true, the following line is always executed:
any_list.remove(x)
This removes the first x from the list, making the list shorter, while still iterating. This causes the for loop to skip items as it'll move the pointer to the next element. See Loop "Forgets" to Remove Some Items for why that is.
All in all, you end up with 4, then 3 items in the list, so list_item[3] then fails and throws the exception.
The proper way to remove duplicates is to use a set object:
def repeating(any_list):
return list(set(any_list))
because a set can only hold unique items. It'll alter the order however. If the order is important, you can use a collections.OrderedDict() object:
def repeating(any_list):
return list(OrderedDict.fromkeys(any_list))
Like a set, a dictionary can only hold unique keys, but an OrderedDict actually also keeps track of the order of insertion; the dict.fromkeys() method gives each element in any_list a value of None unless the element was already there. Turning that back in to a list gives you the unique elements in a first-come, first serve order:
>>> from collections import OrderedDict
>>> a_list = [1, 4, 3, 2, 3]
>>> list(set(a_list))
[1, 2, 3, 4]
>>> list(OrderedDict.fromkeys(a_list))
[1, 4, 3, 2]
See How do you remove duplicates from a list in whilst preserving order? for more options still.
The easiest way to solve your issue is to convert the list to a set and then, back to a list...
def repeating(any_list):
print list(set(any_list))
You're probably having an issue, because you're modifying the list (removing), while iterating over it.
If you want to remove duplicates in a list but don't care about the elements formatting then you can
def removeDuplicate(numlist):
return list(set(numlist))
If you want to preserve the order then
def removeDuplicate(numlist):
return sorted(list(set(numlist)), key=numlist.index)
This question already has answers here:
How do I remove duplicates from a list, while preserving order?
(31 answers)
Closed 8 months ago.
What I am trying to do is write a method that takes a list as an argument and uses a set to return a copy of the list where each element only occurs once, as well as having the elements in the new list occur in order of their first occurrence in the original list. I HAVE to use a set for this, however, I can't make it so that the output is in the right order while having a quick result.
If I put something like this:
def unique(a):
return list(set(a))
and passed a list with millions of elements, it would give me a result quickly, but it wouldn't be ordered.
So what I have right now is this:
def unique(a):
b = set(a)
c = {}
d = []
for i in b:
c[a.index(i)] = i
for i in c:
d.append(c[i])
return d
This gives me the result I want, but not fast enough. If I pass a list with a million elements, I could be waiting for half an hour, whereas the one liner up there takes less than a second. How could I solve this problem?
>>> from collections import OrderedDict
>>> items = [1, 2, 3, 'a', 2, 4, 'a']
>>> OrderedDict.fromkeys(items).keys()
[1, 2, 3, 'a', 4]