Usually in Python if we put lst[-1] we mean the item at the length of lst. But I would like to make it where it means "before index 0". Is such a thing possible? I've looked around but I haven't found anything useful yet.
Currently I'm working on a robot that maps out a room. The indices will be used for coordinates in the room so if my robot starts at (0, 0) in a 2d list then I need to be able to traverse the X & Y axes in both the positive and negative directions. that is why I need this I need to be able to use 0 as not the beginning of the list but rather is just a part of the list.
It sounds like your program won't know how big the room is when it's run, since it's using a robot to map it. In which case let's stop trying to use list indexes and use something better-suited to the task of handling arbitrary keys.
from collections import defaultdict
cur_map = defaultdict(dict)
This creates a dict object that, when you assign an unknown key to it, creates a new dict as a value. In other words:
cur_map[0]['foo'] = 'bar'
# cur_map now looks like
# {0: {'foo': 'bar'}}
Dictionaries can take arbitrary hashable objects as keys, so you can do
cur_map[0][0] = "START"
cur_map[0][-1] = "South x1"
cur_map[-1][-1] = "South x1, West x1"
# etc
Yes, you can. If you for example want a 2D list with x-indexes -50 to 50 and y-indexes -50 to 50, then simply make a 101x101 list and interpret negative indexes as being "before". Up to you how you think of them.
I've used this before, for example in a maze puzzle, to avoid boundary-checking in my main code. I simply added two rows and two columns in addition to the actual field and put "walls" in the cells of the two last rows and columns. Index -1 then simply represented the row above the one of index 0 and the column left of the one with index 0.
Related
I have a list with ordered dictionaries. These ordered dictionaries have different sizes and can also have the same size(for example, 10 dictionaries can have the length of 30 and 20 dictionaries can have the length of 32). I want to find the maximum number of items a dictionary from the list has. I have tried this, which gets me the correct maximum length:
maximum_len= max(len(dictionary_item) for dictionary_item in item_list)
But how can I find the dictionary fields for which the maximum_len is given? Say that the maximum_len is 30, I want to also have the dictionary with the 30 keys printed. It can be any dictionary with the size 30, not a specific one. I just need the keys of that dictionary.
Well you can always use filter:
output_dics=filter((lambda x: len(x)==maximum_len),item_list)
then you have all the dictionarys that satisfies the condition , pick a random one or the first one
Don't know if this is the easiest or most elegant way to do it but you could just write a simple function that returns 2 values, the max_length you already calculated but also the dict that you can get via the .index method and the max_length of the object you were searching for.
im talking about something like this:
def get_max(list_of_dict):
plot = []
for dict_index, dictionary in enumerate(list_of_dict):
plot.append(len(dictionary))
return max(plot), list_of_dict[plot.index(max(plot))]
maximum_len, max_dict = get_max(test)
tested it, works for my case, although i have just made myself a testlist with just 5 dicts of different length.
EDIT:
changed variable "dict" to "dictionary" to prevent it shadowing from outer scope.
I have a list of lists say, for example:
directions = [[-1,0,1],[1,0,4],[1,1,2][-1,1,2]]
now, in any of the nested lists the index [2] is of no importance in the test.
I want to try to find if the first two values in any of the nested lists match the inverse of any other, To clarify further by inverse I mean the negative value In python code. preferable with only one line but if that not possible than a work around to get the same effect.
and if is condition is true and the third values of the two nested lists should be added together and stored in the second original list in the check function and the second list which was the inverse one should be deleted.
So
if nested list's first 2 values == -another nested list's first 2 values
add their third values together
list delete(inverse list)
I hope this makes a little more sense.
I have tried this below but I still cant get it to skip the 3 value or index 2
listNum = 0
while len(directions) > listNum:
if (-directions[listNum][0], -directions[listNum][1], anything(Idk)) in directions:
index = index(-directions[listNum][0], -directions[listNum][1], anything(Idk))
directions[listNum][2] += directions[index][2]
directions.del(index)
But I don't know what to put where I put anything(Idk)
I am but a humble coding grasshopper and have a simple question.
Let:
x = ['this','is','a','list']
How come:
x[100:101]
outputs an empty list like expected, yet:
x[100]
is an error?
Ditto for strings, please and thank you.
It is basically a design choice of Python, and there is not really something right or wrong with either an error for x[100:101] versus giving an empty list.
Note that x[slice(...)] will always return a container (with the same type of x), while x[int] will always access the element at the specified position.
I think it was a design decision with Python. When selecting a range, Python will return everything it can even if the list indices are out of range. But if selecting a single key or index, Python will give an error if the key doesn’t exist.
I guess the logic is that if you are selecting a range, you probably don’t care as much about the items than if you were select each item individually
calling x[100:101] or x[100]calls thegetitem` function. according to the docs, this function should take in an integer or a slice object
https://docs.python.org/3/reference/datamodel.html#object.getitem
When you call x[100] you are trying to look up the non-existent 100th item, raising an error. There is no 100th object.
When you call x[100:101] you are passing in a slice object. this is handled differently. You get a slice of the list. In this case you get back [] because there are no items in that range.
Its still confusing.
Python slicing uses right-open intervals.
This has nice properties like the slices [a:b] and [b:c] not overlapping. Also the length of the slice [a:b] is easy to calculate and verify: it is simply b - a, not b - a + 1, and an empty slice looks like [3:3], not [3:2]. [0:5] and [5:10] cuts a ten element list nicely in half.
One way to think of it is to imagine a ruler, where the indices being points between the elements:
|e0|e1|e2|
0 1 2 3
The index of an element is the number to the left (closer to zero).
The slice [0:2] goes from the | mark above zero, to the | mark above 2, spanning e1 and e2.
We can think of that 2 as referencing the right edge of element [1] rather than denoting the index of the excluded element [2].
I have the following situation:
I am generating n combinations of size 3 from, made from n values. Each kth combination [0...n] is pulled from a pool of values, located in the kth index of a list of n sets. Each value can appear 3 times. So if I have 10 values, then I have a list of size 10. Each index holds a set of values 0-10.
So, it seems to me that a good way to do this is to have something keeping count of all the available values from among all the sets. So, if a value is rare(lets say there is only 1 left), if I had a structure where I could look up the rarest value, and have the structure tell me which index it was located in, then it would make generating the possible combinations much easier.
How could I do this? What about one structure to keep count of elements, and a dictionary to keep track of list indices that contain the value?
edit: I guess I should put in that a specific problem I am looking to solve here, is how to update the set for every index of the list (or whatever other structures i end up using), so that when I use a value 3 times, it is made unavailable for every other combination.
Thank you.
Another edit
It seems that this may be a little too abstract to be asking for solutions when it's hard to understand what I am even asking for. I will come back with some code soon, please check back in 1.5-2 hours if you are interested.
how to update the set for every index of the list (or whatever other structures i end up using), so that when I use a value 3 times, it is made unavailable for every other combination.
I assume you want to sample the values truly randomly, right? What if you put 3 of each value into a list, shuffle it with random.shuffle, and then just keep popping values from the end of the list when you're building your combination? If I'm understanding your problem right, here's example code:
from random import shuffle
valid_values = [i for i in range(10)] # the valid values are 0 through 9 in my example, update accordingly for yours
vals = 3*valid_values # I have 3 of each valid value
shuffle(vals) # randomly shuffle them
while len(vals) != 0:
combination = (vals.pop(), vals.pop(), vals.pop()) # combinations are 3 values?
print(combination)
EDIT: Updated code based on the added information that you have sets of values (but this still assumes you can use more than one value from a given set):
from random import shuffle
my_sets_of_vals = [......] # list of sets
valid_values = list()
for i in range(my_sets_of_vals):
for val in my_sets_of_vals[i]:
valid_values.append((i,val)) # this can probably be done in list comprehension but I forgot the syntax
vals = 3*valid_values # I have 3 of each valid value
shuffle(vals) # randomly shuffle them
while len(vals) != 0:
combination = (vals.pop()[1], vals.pop()[1], vals.pop()[1]) # combinations are 3 values?
print(combination)
Based on the edit you could make an object for each value. It could hold the number of times you have used the element and the element itself. When you find you have used an element three times, remove it from the list
How do I search for a paticular list within a list of lists so specifically:
Say i have a list grid_list that contains many other lists and i want to search through the grid_list to find one of these specifically how could i do this? here is the code that i think should work but
doesnt:
import sys #sys has been imported to take in user input
import random #random has been imported to generate random numbers to store the ants food in in the grid
#grid list is a generated list used to store grid values
grid_list = []
grid_size=0 #grid size is a variable that is assigned a value in function space and used in other functions, has default value of zero
ant_position="" #ants current position in grid used in more than one function
food_location="" #foods position in grid used in more than one function
#function for setting up a grid
def space():
print("please enter the size of the square grid you want")
#grid size is assigned by user input
global grid_size
grid_size = int(sys.stdin.readline())
#embedded for loops to set up a list that stores grid points
for count in range(0,grid_size):
x_number= count+1 #x number is the x number of the cell in the grid
for count in range(0,grid_size):
y_number= count+1 # y number is the y number of the cell in the grid
grid_list.append([x_number,y_number,0,0,0]) #this stores a list within a list, so the first two values of the second list represent the co-ordinates of the cell the last three represent pheromone, food location, ant location (both food and ant location take value of one if either are in there)
def locations():
global food_location
food_location_x = (random.randint(1,grid_size)) #gives the x value of the cell the food is stored in
food_location_y = (random.randint(1,grid_size)) #gives the y value of the cell the food is stored in
food_location = [food_location_x,food_location_y,0,0,0] #gives the full location of the food and will use this to in other functions to reference the grid list
for count in range(0,4):
grid_list[[grid_list.index([food_location])][count]] = [food_location_x,food_location_y,0,1,0]
print(grid_list[grid_list.index(food_location)])
this code sets up a list that contains many other lists, (space function) and then changes one of the lists in the list (grid_list) to represent that it contains the food.
However instead of this working i get a value error saying that [2,1,0,0,0] is not in the list or whatever other grid value the code gives (2 and 1 can be replaced by any positive integer in this situation). Can someone please explain to me how i can change this so it searches for it correctly?
There are two bugs in this code. The first, previously noted by roippi, is that you are putting food_location in a list before searching for it. The second is that you are doing this same thing four times. You are searching for [x,y,0,0,0], replacing it, and then searching for the same [x,y,0,0,0] in the list. Since you just replaced that element, it does not exist any more and you get the error you're seeing.
As roippi noted, a better way to get 4 positions to replace would be to use
random.sample(grid_list, 4)
And modify each of the four lists returned so that the fourth element was 1. random.sample will return the same lists that are in the grid_list, so modifying the elements of these lists will modify them in the grid_list as well.
One bug I can see:
grid_list.index([food_location])
You are putting food_location into a list. But food_location is already a list, so now you have a list within a list. When you do grid_list.index(that), it tells you that there's no doubly-nested list in grid_list.
Honestly it looks like you're doing a really funky method to get a random sampling of grid_list. You should be using random.choice or random.sample to get one or many random elements out of your collection, respectively.
You're representing a two-dimensional array as a list of lists, and you're trying to search it for an item. You simply can't use grid_list.index() for such a search. The items in grid_list are your grid's columns, so grid_list.index(item) is comparing the item to entire columns, therefore not finding a match.
I recommend defining a function which will do the search you want. Something like:
def find_in_grid(grid, item_to_find):
"""search for a given item in a grid
If found, the indexes (x, y) are returned. Otherwise, returns None.
"""
for row in range(len(grid)):
for column in range(len(grid[row])):
if grid[row][column] == item_to_find:
return (row, column)
return None # item not found in the grid
Of course, it would be even better to define a simple Grid class and give it a find() or index() method.