Hidden id on tkInter Listbox - python

I'm wondering if it's possible to somehow store a hidden id along with each entry on a Listbox. The reason for this is that I've got a table which contains a unique id which is from a database (not visible to the user but used to uniquely identify each record) I'm caching the table in memory and using a dictionary keyed on the id
I'd like to create a Listbox which allows me to select one of the records - the displayed text would not be the unique id but a descriptive field (such as 'Name') which is probably unique but this is not enforced and there is no index on it. So for example, If I have:
Id Name
-- ----
2 Rod
5 Jane
15 Freddy
Then selecting Jane, I would somehow be able to easily access the id 5
My problem is that I can't find a way to associate the unique id (5) with the selection (Jane) so that I can easily identify the cached record. I know that I can use control variables but this just gives me a list of all the strings in the list - not what I want. Also, the index (for example on insert) does not seem to be reliable for this purpose.
The only way that I've managed to do this is to have another dictionary mapping the name to the id. For a number of reasons, this is sub-optimal.
Am I missing something here? Is there an easier way of doing this?

Keep your ids in a list, then use the .curselection() index to map these back to the row ids, as long as you keep the ordering the same.
In your example, Jane is the second choice in your list, so if selected .curselection() returns 1. If you have a rowids list in the same order, rowids[1] will be 5:
>>> rowids = [2, 5, 15]
>>> rowids[listbox.curselection()]
5
Slightly more efficient than mapping names to rowids in a dictionary.

If you use the ttk.Treeview widget instead of a Listbox, you can store the id in an invisible column.

Related

Optimal data structure for streaming data

I have a stream of data of the form [id, name, act, value, type].
id is an integer, name a string, act can be 'add', 'update' or 'delete', value is an integer, type is either L or R. We can only add once an id, perform multiple updates and then delete the id. I obviously look for a data structure that will allow me to insert those data efficiently.
I also need to be able to get the highest L value by name and the lowest R value by name at each moment the fastest way possible.
I believe I will need to use heap to get in a constant time min and max values by name. My problem is that I don't manage to find a way to also have the possibility to delete and update existing data at the same time.
The phrasing is a bit unclear here. Let me try and rephrase: you are looking for a good data structure such that, given a stream of operations in the form given above, you can add, delete, or update items (found using their id number). And you'd also like to maintain a few summary statistics about the whole data structure such as highest L and lowest R value.
Does this sound correct?
A dictionary of dictionaries sounds like it's probably the right answer if your id numbers are not over a specific range, or a list of dictionaries if they are.
Sorting makes this a different sort of problem. So you are instead looking for a way to add and subtract data entries into a data structure sorted alphabetically on their string names? One common way to do this is with a binary search tree. A BST will give you an insertion time complexity of O(log(n)) with n elements in the tree. At each element you can store the other data. Then you can separately maintain the highest L and lowest R values and update these each time a value is added that exceeds on of these values. If you remove a value equal to one of these limits, you'll have to traverse the whole data structure to get the new limit value.

Tkinter - Return column number of selected treeview

How do I get the number of the column that is selected in a tkinter treeview?
Right now I'm using tree.focus() but it returns something like I001 or I00A and I have no idea how to convert that to a number.
I can't index the tree because there are multiple items with the same name in it, and I want to know the exact column the user clicks on.
What I expect is to click the first item and get the integer 0 back, etc.
Thanks, please ask questions if I was confusing...
Here are docs for Treeview.
You have used the term "column" repeatedly, but when you say "multiple items with the same name" and refer to "first item" it sounds a lot like you're talking about rows.
If you want the column, you'll need to capture the click event using treeview.bind("<Button-1>", callback) or a variant of that. You would then use treeview.identify_column to get the column index based on the event's x location (keep in mind, per the docs, that if your columns are rearranged you may need to do some extra work). Here are two links if you need information on events.
If you were actually talking about rows, you can use treeview.selection() to get a list of iids of selected items, and then feed them into treeview.index() to get the 0-index of the row that you were talking about.

python adding unique items to a huge table

I have a very large list of items (10M+) that must be put in a table with three columns (Item_ID,Item_name,Item_count)
The items in the table must be unique.
We are adding the items one by one.
When each new item is added, we need to check:
if it is on the table, update its count +1, and retrieve its ID
if not on the table, insert it in the table, assign it an ID and set its count to 1
I have tried with different database implementations (MySQL and sqlite, python shelve, and my own flat file implementation), but the problem is always the same: the more rows there are on the table, the more lookup operations will be needed (for a table 10,000 rows, will need to do around 10,000*10,000 at least lookups for the following 10,000 items.
Indexing the database may sound a good idea to optimize, but my understanding is that the indexing is done after the bulk of the data is inserted, not updated with each insertion.
So, how can we add such large number of items into a table the way described?
you can use set() to check if that item is already on the list
im assuming that you have a list of list(w=[[id,name,count],[id,name,count],..])
r=[e[1] for e in list] <--- this will create a new list that only contains the names
if(len(set(r+item[1]))== len(set(r))){ <-if this is true then the item is on list
list[list.index(item)][countIndex]+= 1 <-- count +1
list[list.index(item)][idindex] <-- to retrieve id
}else{
list=list+[id,item-name,count] <-- this will add the item
}
if you have the list on your database its the same, just use queries the get and set the info.
to set the id you can search the last item id and set +1 like this
list=list+[list[len(list)][id]+1,item-name,count]

Finding the distribution of a field in a list of objects?

I have a list of objects. Each object has a field called grade whose value is between 0 and 5. Now I want to see the distribution of this field across my list of objects. Is there any way to find it?
I know I can iterate over the whole objects and find it out but I don't want to do that.
As near as I can tell, using a table Table with a grade column you need something like this:
counts = Table.objects.annotate(count=Count("grade", distinct=True)
This adds a count attribute to each member of the counts query set, which you can access just like a regular database column.

Redis and redis-py: Storing abstract objects

In Python I have objects that contain other objects. What is the best way to represent this using Redis?
This answer adresses this. The solution is basically that you give every object an id and if a objectA contains objectB what you store in objectA is the id of objectB. If there's nothing better, I guess this seems reasonable.
Now my question is, how do I generate these ids? Lets say that my objects are users that contain other objects called items. Each unique item I give a unique id. But when a new item is created, how to I make sure that the id I give the new item doesn't exist already, without having to check the all the existing ids? Suppoose for example that I'm storying all the existing items in the redis namespace as item:int, item:5313, item:1234 etc. I want to create a new item, how do I check the existing ids in a way that's efficient?
Thanks.
You can use autoincrement id counter, like this:
redis 127.0.0.1:6379> incr next_id:user
(integer) 1
redis 127.0.0.1:6379> incr next_id:user
(integer) 2

Categories

Resources