I'm trying to simply append to a list of lists but cannot find a clean example of how to do that. I've looked at dozens of examples but they are all for appending to a one-dimensional list or extending lists.
Sample code:
testList = []
print(testList)
testList.append(3000)
print(testList)
testList[3000].append(1)
testList[3000].append(2)
print(testList)
Expected result:
testList[3000][1, 2]
Actual result:
[]
[3000]
Traceback (most recent call last):
File ".\test.py", line 5, in <module>
testList[3000].append(1)
IndexError: list index out of range
The first problem I see is that when you call testList.append() you are including the [3000]. That is problematic because with a list, that syntax means you're looking for the element at index 3000 within testList. All you need to do is call testList.append(<thing_to_append>) to append an item to testList.
The other problem is that you're expecting [1, 2] to be a separate list, but instead you're appending them each to testList.
If you want testList to be composed of multiple lists, a good starting point would be to instantiate them individually, and to subsequently append to testList. This should help you conceptualize the nested structure you're looking for.
For example:
testList = []
three_k = [3000]
one_two = [1, 2]
testList.append(three_k)
testList.append(one_two)
print(testList)
From there, the you can actually use the indexes of the nested lists to append to them. So if [3000] is the list at index 0 (zero), you can append to it by doing: testList[0].append(<new_append_thing>).
First, thank you to everyone for the quick responses. Several of you got me thinking in the right direction but my original question wasn't complete (apologies) so I'm adding more context here that's hopefully helpful for someone else in the future.
wp-overwatch.com jogged my memory and I realized that after working with only dictionaries in my application for days, I was treating the "3000" like a dictionary key instead of the list index. ("3000" is an example of an ID number that I have to use to track one of the lists of numbers.)
I couldn't use a dictionary, however, because I need to add new entries, remove the first entry, and calculate average for the numbers I'm working with. The answer was to create a dictionary of lists.
Example test code I used:
testDict = {}
blah10 = 10
blah20 = 20
blah30 = 30
blah40 = 40
exampleId = 3000
if exampleId == 3000:
testDict[3000] = []
testDict[3000].append(blah10)
testDict[3000].append(blah20)
print(testDict)
testDict[3000].pop(0) # Remove first entry
print(testDict)
testDict[3000].append(blah30) # Add new number to the list
average = sum(testDict[3000]) / len(testDict[3000])
print(average)
if exampleId == 3001:
testDict[3001].append(blah30)
testDict[3001].append(blah40)
Result:
{3000: [10, 20]}
{3000: [20]}
25.0
testList[3000].append(1) is telling Python to grab the 3000th item in the list and call the append function on it. Since you don't have 3000 items in the list, that's why you're getting that error.
If you want to lookup an item by a value such as 3000 instead of by its position in the list, then what you're wanting is not a list but a dictionary.
Using a dictionary you can do:
>>> testList = {} # use curly brackets for a dictionary
>>> print(testList)
{}
>>> testList[3000] = [] # create a new item with the lookup key of 3000 and set the corresponding value to an empty list
>>> print(testList)
{3000: []}
>>> testList[3000].append(1)
>>> testList[3000].append(2)
>>> print(testList)
{3000: [1, 2]}
>>>
It is because according to your program the python interpreter will look for the 3000 index at the list and try to append the given number in the index of 3000 but there is not that number so it will print error.
To fix it:
testList = []
print(testList)
testList.append(3000)
print(testList)
testList.append([1])
testList[1].append(2)
print(testList)
Using the index you can append the value as I appended.
list.append adds an object to the end of a list. So doing,
listA = []
listA.append(1)
now listA will have only the object 1 like [1].
you can construct a bigger list doing the following
listA = [1]*3000
which will give you a list of 3000 times 1 [1,1,1,1,1,...].
If you want to contract a c-like array you should do the following
listA = [[1]*3000 for _ in range(3000)]
Now you have a list of lists like [[1,1,1,1,....], [1,1,1,....], .... ]
PS Be very careful using [1]*3000 which in this case works
but in case you use it with a variable it will have side effects. For example,
a = 1
listA = [a]*3000
gives you the same result but if any of the variables 'a' change then all will be changed the same way.
The most safe is, using list comprehensions
a = 1
listA = [a for _ in range(3000)]
In order to update any value, just do the following,
listA[656] = 999
Lastly, in order to extend the above list just type
listA.append(999)
and then at the index 3000 (starting from zero) you will find 999
Related
If I have a master_list (list of lists), I want to know what the simplest way would to sort it by x value (I'll call it score). Score (a float) is derived by calling a function that calculates it based on the items in master_list[i] (a list).
The way I was going about is like this:
for i in range(len(master_list):
# call get_score(master_list[i]) (function that calculates score for master_list[i]) and
insert to index 0 in master_list[i]
sorted_list = sorted(master_list)
for i in range(len(master_list):
master_list[i].pop(0)
My function get_score() returns the a single float for one of the lists in master_list
It is important not to modify the original master_list, hence why I am removing score from master_list[i]. What I wish to know is if there is any way to accomplish without adding score to each master_list[i], then removing it.
I also tried something like this but I don't believe it would work:
score_sorted = sorted(master_list, key=get_score(iterm for item in master_list))
Expected output:
master_list = [['b', 1]['a', 2]['c', 3]]
If the score for master_list[i] are 3, 2, 1 for all items respectively then the ouput would be:
master_list_with_score = [[3,'b', 1][2,'a', 2][1,'c', 3]]
sorted_by_score_master_list = [['c', 3]['a', 2]['b', 1]]
Sorry about the formatting, it's my first time posting. Let me know if there is need for any clarification
You're just supposed to provide the function, sorted will call it on the list elements itself.
sorted(master_list, key=get_score)
Try it online!
I would keep a seperate list of scores.
master_list = master_list
score = get_score(master_list[i]) # i am assuming it returns a list of scores for the same index in master list
sorted(zip(score, master_list)) # then master list is sorted by the scores
If you want a seperated sorted list,
sorted_master_list = [i for (score,i) in sorted(zip(score, master_list))]
code A :
t1 = {}
t1[0] = -5
t1[1] = 10.5
code B :
t2 = []
t2[0] = -5
t2[1] = 10.5
why code B has "IndexError: list assignment index out of range" and how to solve it?
Dictionaries are hashsets. They pair arbitrary (hashable) keys with values, and there is no expectation that those keys are consecutive, or even in fact numbers
replacement_dict = {'old_name': 'new_name'} # you could use this to implement a find/replace
By comparison, lists are densely-packed and their indices (not keys -- this is a different term accessed the same way with the object[index] notation) are numbers. Because of this, you can't just access a random value that's greater than the length of the list, you must use append instead.
lst = []
lst[0] = 'blah' # throws an IndexError because len(lst) is 0
lst.append('blah')
assert lst[0] == 'blah
Dictionaries work like key-value pairs. Every time you assign a new value in a dictionary, you create a new key-value pair.
A list is like an array that you can extend at will, but if you try to access an index that is over its current size, it will return an error. You typically extend a list by using t2.append(value).
A dictionary allows assignment of elements that don't exist yet. Lists don't. That's just the way they're designed.
You can fix this two ways. First is to initialize the list to the size it needs to be:
t2 = [None]*2
The second is to call append instead of using =:
t2 = []
t2.append(-5)
t2.append(10.5)
A dictionary stores data with name values.
dictionary = {"name": "value"}
print(dictionary["name"])
# Prints "value".
A list stores a sequence of values. There aren't any names for the values, they are accessed via an index.
list = ["value", "other value"]
print(list[0])
# Prints "value".
To fix your problem use append.
t2 = []
t2.append(-5)
t2.append(10.5)
In a for loop, I'm trying to understand when to refer to an item by its item name and when to refer to the item as an index of the list I'm looping through.
In the code pasted below, I don't understand why "idx" is referred to in the "if" statement with a reference to the list index but then in the definition of maximum_score_index, it is referred to by itself.
def linear_search(search_list):
maximum_score_index = None
for **idx** in range(len(search_list)):
if not maximum_score_index or **search_list[idx]** > search_list[maximum_score_index]:
maximum_score_index = **idx**
return maximum_score_index
I'd love to have an explanation so I can differentiate in the future and some examples to show the difference so I can understand.
In Python, range(num) (more or less) returns a list of numbers from 0 through num - 1. It follows that range(len(my_list)) will generate a list of numbers from 0 through the length of my_list minus one. This is frequently useful, because the generated numbers are the indices of each item in my_list (Python lists start counting at 0). For example, range(len(["a", "b", "c"])) is [0, 1, 2], the indices needed to access each item in the original list. ["a", "b", "c"][0] is "a", and so on.
In Python, the for x in mylist loop iterates through each item in mylist, setting x to the value of each item in order. One common pattern for Python for loops is the for x in range(len(my_list)). This is useful, because you loop through the indices of each list item instead of the values themselves. It's almost as easy to access the values (just use my_list[x]) but it's much easier to do things like access the preceding value (just use my_list[x-1], much simpler than it would be if you didn't have the index!).
In your example, idx is tracking the index of each list item as the program iterates through search_list. In order to retrieve values from search_list, the program uses search_list[idx], much like I used my_list[x] in my example. The code then assigns maximum_score_index to the index itself, a number like 0, 1, or 2, rather than the value. It's still easy to find out what the maximum score is, with search_list[maximum_score_index]. The reason idx is not being used as a list accessor in the second case is because the program is storing the index itself, not the value of the array at that index.
Basically, this line:
if not maximum_score_index or **search_list[idx]** > search_list[maximum_score_index]:
maximum_score_index = **idx**
Can be thought of as:
if (this is the first pass) or (element at index > this loop-iteration element):
keep this index as largest element
What I recommend to do:
Go through the code, on a piece of paper and iterate over a list to
see what the code does
Write the code in any IDE, and use a debugger
to see what the code does
Are you looking for the index of the highest element in the list or the value?
If you are looking for the value, it can be as simple as:
highest = max(search_list)
You could also use enumerate, which will grant you "free" access to the current index in the loop:
>>> search_list
[10, 15, 5, 3]
>>> maximum_score_index = None
>>> for idx, value in enumerate(search_list):
... if not maximum_score_index or search_list[idx] > value:
... maximum_score_index = idx
...
>>> maximum_score_index
1
>>> search_list[maximum_score_index]
15
How can I divide all of the data in the second row by two?
recipe = [
['eggs', 'flour', 'meat'],
[4, 250, 5],
['large','grams', 'kg'],
]
I've tried starting with
for row[2] in recipe:
But I get an error saying:
Traceback (most recent call last):
File "/Users/g/Documents/reicpe.py", line 7, in
for row[2] in meat_pie:
NameError: name 'row' is not defined
You can also use list comprehension and do it in one single line without the for-loop:
recipe[1] = [num / 2 for num in recipe[1]]
Code Explanation [num / 2 for num in recipe[1]]:
recipe[1]: This is a list, it's the second element of recipe list
The second element of recipe is: [4, 250, 5]
for num in recipe[1]: This mean that we're going to loop over the elements of recipe[1], so num it's a variable, and it's value changes over the list elements in each iteration.
num / 2: It's obvious that we get num and divide by 2
recipe = [
['eggs', 'flour', 'meat'],
[4, 250, 5],
['large','grams', 'kg'],
]
Leaving aside this would be far better as a dictionary, if you want to divide the quantities by two, and change what you have stored :
for quantity, index in enumerate(recipe[1])
recipe[1][index] = quantity/2
A better way would be to use a dictionary, which allows you to give names to data items :
recipe = {"eggs":{"quantity":4, "measurement":"large"},
"flour":{"quantity":250,"measurement":"grams"},
"meat":{"quantity":5,"measurement":"kg"}}
and now division by two becomes :
for ingredient in recipe:
recipe[ingredient]["quantity"] = recipe[ingredient]["quantity"]/2
and print the recipe becomes :
for ingredient in recipe:
print "{} {} {}".format(recipe[ingredient]["quantity"], recipe[ingredient]["measurement"], ingredient)
this generates :
4 large eggs
250 grams flour
5 kg meat
and no faffing about with index numbers etc.
recipe[1] gives you the second list inside the recipe list. Remember, list index always start with 0.
Then:
for row in recipe[1]:
Will iterate with row taking the value of each of the values inside recipe[1].
You're trying to iterate on the wrong portion. When you use the statement: for i in list, i is created as a new variable (as if you had just stated i = 5). So at that point, it does not have a getter (index or otherwise) for element 5 (and it is not a valid variable name).
To fix your iteration issue try:
for row in mylist[index]:
That will iterate over the list at index in mylist, of course remember that lists are 0 indexed (your numbers are at index 1).
You're going to have another issue shortly with updating the values in your array, however, since the process will create a copy the way you're doing it. A simple fix is to use enumerate (but I will leave that up to you to try out before giving it to you!)
This is an incredibly simple question (I'm new to Python).
I basically want a data structure like a PHP array -- i.e., I want to initialise it and then just add values into it.
As far as I can tell, this is not possible with Python, so I've got the maximum value I might want to use as an index, but I can't figure out how to create an empty list of a specified length.
Also, is a list the right data structure to use to model what feels like it should just be an array? I tried to use an array, but it seemed unhappy with storing strings.
Edit: Sorry, I didn't explain very clearly what I was looking for. When I add items into the list, I do not want to put them in in sequence, but rather I want to insert them into specified slots in the list.
I.e., I want to be able to do this:
list = []
for row in rows:
c = list_of_categories.index(row["id"])
print c
list[c] = row["name"]
Depending on how you are going to use the list, it may be that you actually want a dictionary. This will work:
d = {}
for row in rows:
c = list_of_categories.index(row["id"])
print c
d[c] = row["name"]
... or more compactly:
d = dict((list_of_categories.index(row['id']), row['name']) for row in rows)
print d
PHP arrays are much more like Python dicts than they are like Python lists. For example, they can have strings for keys.
And confusingly, Python has an array module, which is described as "efficient arrays of numeric values", which is definitely not what you want.
If the number of items you want is known in advance, and you want to access them using integer, 0-based, consecutive indices, you might try this:
n = 3
array = n * [None]
print array
array[2] = 11
array[1] = 47
array[0] = 42
print array
This prints:
[None, None, None]
[42, 47, 11]
Use the list constructor, and append your items, like this:
l = list ()
l.append ("foo")
l.append (3)
print (l)
gives me ['foo', 3], which should be what you want. See the documentation on list and the sequence type documentation.
EDIT Updated
For inserting, use insert, like this:
l = list ()
l.append ("foo")
l.append (3)
l.insert (1, "new")
print (l)
which prints ['foo', 'new', 3]
http://diveintopython3.ep.io/native-datatypes.html#lists
You don't need to create empty lists with a specified length. You just add to them and query about their current length if needed.
What you can't do without preparing to catch an exception is to use a non existent index. Which is probably what you are used to in PHP.
You can use this syntax to create a list with n elements:
lst = [0] * n
But be careful! The list will contain n copies of this object. If this object is mutable and you change one element, then all copies will be changed! In this case you should use:
lst = [some_object() for i in xrange(n)]
Then you can access these elements:
for i in xrange(n):
lst[i] += 1
A Python list is comparable to a vector in other languages. It is a resizable array, not a linked list.
Sounds like what you need might be a dictionary rather than an array if you want to insert into specified indices.
dict = {'a': 1, 'b': 2, 'c': 3}
dict['a']
1
I agree with ned that you probably need a dictionary for what you're trying to do. But here's a way to get a list of those lists of categories you can do this:
lst = [list_of_categories.index(row["id"]) for row in rows]
use a dictionary, because what you're really asking for is a structure you can access by arbitrary keys
list = {}
for row in rows:
c = list_of_categories.index(row["id"])
print c
list[c] = row["name"]
Then you can iterate through the known contents with:
for x in list.values():
print x
Or check if something exists in the "list":
if 3 in list:
print "it's there"
I'm not sure if I understood what you mean or want to do, but it seems that you want a list which
is dictonary-like where the index is the key. Even if I think, the usage of a dictonary would be a better
choice, here's my answer: Got a problem - make an object:
class MyList(UserList.UserList):
NO_ITEM = 'noitem'
def insertAt(self, item, index):
length = len(self)
if index < length:
self[index] = item
elif index == length:
self.append(item)
else:
for i in range(0, index-length):
self.append(self.NO_ITEM)
self.append(item)
Maybe some errors in the python syntax (didn't check), but in principle it should work.
Of course the else case works also for the elif, but I thought, it might be a little harder
to read this way.