Does anyone know of any implementations of or papers about key-based data structures that allow mutable keys?
Since the key is being mutated, I'm not sure if 'key' is a correct term but I hope you understand my meaning.
My specific reason for wanting this is to be able to have as efficient as possible neighbor lookup for changing objects without needing to constantly sort parallel lists, constantly restructure a tree or similar structure, or of course deal with the complete collapse of a hashmap when its keys are mutated.
A quick, very simple usage example would be (Java HashMap syntax):
MutableKeyMap<Point, String> m = new MutableKeyMap<Point, String>();
Point p = new Point(5, 6)
m.put(p, "foo");
Point o = new Point(6, 6);
m.put(o, "bar");
// The points are currently neighbors, so
m.get(new Point(o.x - 1, o.y)); // returns "foo".
m.get(new Point(p.x + 1, p.y)); // returns "bar"
// Now here is where most data structures fall apart without some reworking
o.y += 1;
m.get(new Point(o.x - 1, o.y - 1)); // Still returns "foo" because the point "foo" is mapped to has not changed
m.get(new Point(p.x + 1, p.y)); // returns null, as to be expected because o would no longer map to there
m.get(new Point(p.x + 1, p.y + 1)); // A hash map would return null here as well when it should return "bar",
// because the data structure cannot account for the identity-changing mutation of the key.
m.get(o); // even returns null because of this in a hash map.
// Therefore we have effectively deleted the entry. In this data structure the idea would be to maintain this link despite the mutation.
So ideally this data structure would allow the elegance (and if possible, the speed) provided by a map for accessing other elements in the set with respect to another element, while allowing those values by which the elements are accessed to change.
I realize this is probably asking for a "perfect" data structure, but I'm really just interested as to what there exists on this type of data structure, or any ideas that people have.
Related
Is there any hashing algorithm which supports this type of hashing
const hashGen = new HashAlogrithm();
// Imagine hash has an array like data structure
hashGen.push(1); // It appends element to end of array
hashGen.push(2);
hashGen.push(3);
hashGen.unshift(); // removes first pushed element, in this case it will be `1`
const hashGen2 = new HashAlgorithm();
hashGen2.push(2);
hashGen2.push(3);
const hashA = hashGen.generate(); // Generates the Hash value
const hashB = hashGen2.generate();
// hashA and hashB should be equal
I know I can use an array to keep track of pushing. Then on generate I can use some standard hashing algorithm to create hash.
But in my case I will be calling generate function a lot of times after just pushing one number or after removing one letter.
I don't want to recalculate hash whole array each time. I just want to recalculate hash for changed part ( If that makes sense).
I don't need algorithm to be secure.
Let me know if thats even possible and if any algorithm thus that.
I have a Discord.Collection of key-value pairs that stores the information about the number of commands in folders. It looks something like this:
debug - 2
utility - 2
fun - 3
best - 4
replies - 3
I want to sort the collection by folder names (keys) alphabetically (ascending). However, Discord.Collection.sort() sorts ascending by values, meaning my output is debug, utility, fun, replies, best instead of desired best, debug, fun, replies, utility output. Because Discord.Collection extends Map, I looked up js map documentation, but there is no .sort() method. I also looked up sorting in StackOverflow and google, but I only found answers regarding value sorting (or answer in different coding language, which I failed to translate).
I know .sort() accepts lambda expression as parameter, but I don't know how to use it for key sorting - I only ever used it for value sorting.
I don't think the code is necessary for this question, but in case you need to visualise my problem, here is creation of my collection:
const FolderCollection = new Discord.Collection();
//commandList is a Collection of key: command.name, value: {command: command, folder: folder}
commandList.each((cmd) => {
if (FolderCollection.has(cmd.folder)) {
FolderCollection.set(
cmd.folder,
FolderCollection.get(cmd.folder) + 1
);
} else {
FolderCollection.set(cmd.folder, 1);
}
});
Here I want to use my sorted FolderCollection:
FolderCollection.sort().each((cmdCount, categoryName) => {
//...do stuff
});
Feel free to ask for any additional details, but I believe this is all you need to help me with my issue (either direct answer, or link to documentation).
You could use Collection#entries() in a spread operator to turn the collection into an array with the structure [[key, value]], sort that because you'll have access to the whole array (key and value), and then convert it back into a collection if needed. Here's an example with a Map.
// let's say my objective is to sort these
// from lowest to highest relative to the key
// so the result should be:
// Map (3) { 1 => 'bar', 2 => 'baz', 3 => 'foo' }
const map = new Map([[3, 'foo'], [1, 'bar'], [2, 'baz']]);
// make use of [...iterable] to turn an iterable
// into an array
const entries = [...map.entries()];
console.log('Entries: ', entries);
// use array destructuring to access the
// first element of both arrays
entries.sort(([a], [b]) => a - b);
console.log('Sorted Entries: ', entries);
// convert it back to a map (or collection)
// if needed
const newMap = new Map(entries);
Background:
I'm in the beginning of making a game, it has objects that should be able to communicate with each-other by "sound" (not necessarily real sound, can be simulated sound, but it should behave like sound).
That means that they can only communicate with each-other if they are within hearing-range.
Question:
Is there some smart way to test if a another object is within hearing-range without having to loop through all of the other objects? (it would become really inefficient when it's a lot of them).
Note: There can be more than 1 object within hearing-range, so all objects within hearing-range are added to an array (or list, haven't decided yet) for communication.
Data
Currently the object has these properties (it can be changed if needed).
Object {
id = self.id,
x = self.x,
y = self.y,
hearing_max_range = random_range(10, 20), // eg: 10
can_hear_other = []; // append: other.id when in other in range
}
You could look into some clever data structures such as quadtrees or kd-trees, but for a problem with a fixed range query, it might not be too bad to just use simple binning. I'll present the general algorithm in python-like pseudo code.
First construct your bins:
from collections import defaultdict
def make_bin(game_objects, bin_size):
object_bins = defaultdict(list)
for obj in game_objects:
object_bins[(obj.x//bin_size, obj.y//bin_size)].append(obj)
Then query as necessary:
def find_neighbors(game_object, object_bins, bin_size):
x_idx = game_object.x // bin_size
y_idx = game_object.y // bin_size
for x_bin in range(x_idx - 1, x_idx + 2):
for y_bin in range(y_idx - 1, y_idx + 2):
for obj in object_bins[(x_bin, y_bin)]:
if (obj.x - game_object.x)**2 + (obj.y - game_object.y)**2 <= bin_size**2:
yield obj
I am trying to understand the HashTable data structure. I understand that in HashTable we first use HashFunction to coverts a key to hash Code and then using modulo operator to convert Hash code to integer index and which is used to get the location in HashTable where data is placed.
At a high level, the flow is like this?
Key -> Hash Function -> Hash code -> Modulo operator -> integer index -> Store in HashTable
Since the key is stored based on the index as emitted by the modulo operator, my doubt is, what is the underlying data structure which is used to hold the actual data? Is it an array, for array can be accessed using Index.
Can anyone help me understand this?
Though it completely depends on implementation, I would agree that underlying data structure would be array with linked list, since array is convinient to access elements at low cost, while linked list is necessary to handle hash collisions.
Here is example of details how it is implemented in java openjdk Hashtable
Initially it creates array with initial capacity:
table = new Entry<?,?>[initialCapacity];
It checks for capacity threshold everytime when new element is added. When threshold limit is reached it performs rehashing and creates a new array which is double size of old array
int newCapacity = (oldCapacity << 1) + 1;
if (newCapacity - MAX_ARRAY_SIZE > 0) {
if (oldCapacity == MAX_ARRAY_SIZE)
// Keep running with MAX_ARRAY_SIZE buckets
return;
newCapacity = MAX_ARRAY_SIZE;
}
Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
modCount++;
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
table = newMap;
Hashtable Entry forms a linked list. It is used in case of hash collisions, since index for 2 different values would become same and required value is checked through linked list.
private static class Entry<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Entry<K,V> next;
You may want to check other more simple implementations of Hashtables for better understanding.
I want to get the following code to work in the Java ME / J2ME environment. Please help:
Hashtable <Activity, Float>scores = new Hashtable<Activity, Float>();
scores.put(act1, 0.3);
scores.put(act2, 0.5);
scores.put(act3, 0.4);
scores.put(act5, 0.3);
Vector v = new Vector(scores.entrySet());
Collections.sort(v); //error is related to this line
Iterator it = v.iterator();
int cnt = 0;
Activity key;
Float value;
while(it.hasNext()){
cnt++;
Map.Entry e=(Map.Entry)it.next();
key = (Activity)e.getKey();
value = (Float)e.getValue();
System.out.println(key+", "+value);
}
It doesn't work, I get the error:
Exception in thread "main" java.lang.ClassCastException: java.util.Hashtable$Entry cannot be cast to java.lang.Comparable
This points to the line that I've indicated with a comment in the code.
Please help, and bear in mind that I'm using j2me!
The code you've got isn't anywhere near valid J2ME, it's full fat (J2SE) java; J2ME doesn't currently have generics, or a Collections class or a Comparable interface - check for JavaDoc for MIDP 2 and CLDC 1.1, the components of J2ME. Your error mentions those, so definitely didn't come from J2ME, which suggests you might be doing something fundamental wrong in your project setup?
If you do want to do this in J2ME you need to write a sort function yourself, because as far as I can tell no such thing exists. Bubblesort will be easiest to write, since the only way you can easily access sequential members of the hashtable is through Enumerations (via scores.keys() and scores.values()). Assuming you want to sort your activities in ascending order based on the scores (floats) they're associated with, you want something like:
boolean fixedPoint = false;
while (!fixedPoint)
{
fixedPoint = true;
Enumeration e = scores.keys();
if (!e.hasMoreElements()) return;
Object previousKey = e.nextElement();
while (e.hasMoreElements()) {
Object currentKey = e.nextElement();
if ((Float) scores.get(currentKey) > (Float) scores.get(previousKey)) {
swap(currentKey, previousKey);
fixedPoint = false;
}
previousKey = currentKey;
}
}
Also, somewhere you'll need to write a swap function that swaps two elements of the hashtable when given their keys. Worth noting this is NOT the quickest possible implementation -- bubble sort will not be good if you expect to have big big lists. On the other hand, it is very easy with the limited tools that J2ME gives you!
The entrySet method doesn't return the values in the hash table, it returns the key-value pairs. If you want the values you should use the values method instead.
If you want the key-value pairs but sort them only on the value, you have to implement a Comparator for the key-value pairs that compares the values of two pairs, and use the overload of the sort method that takes the Comparator along with the list.