ENH: added HashTable 'lookup' and 'retain' methods
- lookup(): with a default value (const access) For example, Map<label> something; value = something.lookup(key, -1); being equivalent to the following: Map<label> something; value = -1; // bad value if (something.found(key)) { value = something[key]; } except that lookup also makes it convenient to handle const references. Eg, const labelList& ids = someHash.lookup(key, labelList()); - For consistency, provide a two parameter HashTable '()' operator. The lookup() method is, however, normally preferable when const-only access is to be ensured. - retain(): the counterpart to erase(), it only retains entries corresponding to the listed keys. For example, HashTable<someType> largeCache; wordHashSet preserve = ...; largeCache.retain(preserve); being roughly equivalent to the following two-stage process, but with reduced overhead and typing, and fewer potential mistakes. HashTable<someType> largeCache; wordHashSet preserve = ...; { wordHashSet cull(largeCache.toc()); // all keys cull.erase(preserve); // except those to preserve largeCache.erase(cull); // } The HashSet &= operator and retain() are functionally equivalent, but retain() also works with dissimilar value types.
This commit is contained in:
parent
8728e8353f
commit
f73b5b629f
@ -197,8 +197,12 @@ int main(int argc, char *argv[])
|
||||
Info<< "setD has no 11" << endl;
|
||||
}
|
||||
|
||||
Info<< "setB : " << flatOutput(setB) << endl;
|
||||
Info<< "setD : " << flatOutput(setD) << endl;
|
||||
|
||||
setD -= setB;
|
||||
Info<< "setD -= setB : " << flatOutput(setD) << endl;
|
||||
|
||||
// This should not work (yet?)
|
||||
// setD[12] = true;
|
||||
|
||||
|
@ -25,6 +25,7 @@ License
|
||||
|
||||
#include "HashTable.H"
|
||||
#include "List.H"
|
||||
#include "FlatOutput.H"
|
||||
#include "IOstreams.H"
|
||||
#include "IStringStream.H"
|
||||
#include "OStringStream.H"
|
||||
@ -163,15 +164,15 @@ int main()
|
||||
<< "\ntable2" << table2 << nl;
|
||||
|
||||
|
||||
Info<< "\ntable3" << table3
|
||||
<< "\nclearStorage table3 ... ";
|
||||
table3.clearStorage();
|
||||
Info<< table3 << nl;
|
||||
Info<< "\ntable3" << table2
|
||||
<< "\nclearStorage table2 ... ";
|
||||
table2.clearStorage();
|
||||
Info<< table2 << nl;
|
||||
|
||||
table1 =
|
||||
{
|
||||
{"aca", 3.0},
|
||||
{"aaw", 6.0},
|
||||
{"abc", 3.0},
|
||||
{"def", 6.0},
|
||||
{"acr", 8.0},
|
||||
{"aec", 10.0}
|
||||
};
|
||||
@ -195,6 +196,25 @@ int main()
|
||||
// List<scalar> table1vals(table1.begin(), table1.end());
|
||||
// wordList table1keys(table1.begin(), table1.end());
|
||||
|
||||
Info<< "\nFrom table1: " << flatOutput(table1.sortedToc()) << nl
|
||||
<< "retain keys: " << flatOutput(table3.sortedToc()) << nl;
|
||||
|
||||
table1.retain(table3);
|
||||
Info<< "-> " << flatOutput(table1.sortedToc()) << nl;
|
||||
|
||||
Info<< "Lookup non-existent" << nl;
|
||||
|
||||
Info<< table1.lookup("missing-const", 1.2345e+6)
|
||||
<< " // const-access" << nl;
|
||||
|
||||
Info<< table1("missing-inadvertent", 3.14159)
|
||||
<< " // (inadvertent?) non-const access" << nl;
|
||||
|
||||
Info<< table1("missing-autovivify")
|
||||
<< " // Known auto-vivification (non-const access)" << nl;
|
||||
|
||||
Info<<"\ntable1: " << table1 << endl;
|
||||
|
||||
Info<< "\nDone\n";
|
||||
|
||||
return 0;
|
||||
|
@ -227,16 +227,9 @@ void Foam::HashSet<Key, Hash>::operator|=(const HashSet<Key, Hash>& rhs)
|
||||
|
||||
|
||||
template<class Key, class Hash>
|
||||
void Foam::HashSet<Key, Hash>::operator&=(const HashSet<Key, Hash>& rhs)
|
||||
inline void Foam::HashSet<Key, Hash>::operator&=(const HashSet<Key, Hash>& rhs)
|
||||
{
|
||||
// Remove elements not also found in rhs
|
||||
for (iterator iter = this->begin(); iter != this->end(); ++iter)
|
||||
{
|
||||
if (!rhs.found(iter.key()))
|
||||
{
|
||||
this->erase(iter);
|
||||
}
|
||||
}
|
||||
this->parent_type::retain(rhs);
|
||||
}
|
||||
|
||||
|
||||
@ -259,13 +252,9 @@ void Foam::HashSet<Key, Hash>::operator^=(const HashSet<Key, Hash>& rhs)
|
||||
|
||||
|
||||
template<class Key, class Hash>
|
||||
void Foam::HashSet<Key, Hash>::operator-=(const HashSet<Key, Hash>& rhs)
|
||||
inline void Foam::HashSet<Key, Hash>::operator-=(const HashSet<Key, Hash>& rhs)
|
||||
{
|
||||
// Remove rhs elements from lhs
|
||||
for (const_iterator iter = rhs.cbegin(); iter != rhs.cend(); ++iter)
|
||||
{
|
||||
this->erase(iter.key());
|
||||
}
|
||||
this->parent_type::erase(rhs);
|
||||
}
|
||||
|
||||
|
||||
|
@ -277,7 +277,7 @@ public:
|
||||
void operator|=(const HashSet<Key, Hash>& rhs);
|
||||
|
||||
//- Only retain entries found in both HashSets
|
||||
void operator&=(const HashSet<Key, Hash>& rhs);
|
||||
inline void operator&=(const HashSet<Key, Hash>& rhs);
|
||||
|
||||
//- Only retain unique entries (xor)
|
||||
void operator^=(const HashSet<Key, Hash>& rhs);
|
||||
@ -289,7 +289,7 @@ public:
|
||||
}
|
||||
|
||||
//- Remove entries listed in the given HashSet from this HashSet
|
||||
void operator-=(const HashSet<Key, Hash>& rhs);
|
||||
inline void operator-=(const HashSet<Key, Hash>& rhs);
|
||||
|
||||
|
||||
// IOstream Operator
|
||||
|
@ -257,7 +257,7 @@ template<class T, class Key, class Hash>
|
||||
bool Foam::HashTable<T, Key, Hash>::set
|
||||
(
|
||||
const Key& key,
|
||||
const T& newEntry,
|
||||
const T& obj,
|
||||
const bool protect
|
||||
)
|
||||
{
|
||||
@ -284,7 +284,7 @@ bool Foam::HashTable<T, Key, Hash>::set
|
||||
if (!existing)
|
||||
{
|
||||
// Not found, insert it at the head
|
||||
table_[hashIdx] = new hashedEntry(key, newEntry, table_[hashIdx]);
|
||||
table_[hashIdx] = new hashedEntry(key, obj, table_[hashIdx]);
|
||||
nElmts_++;
|
||||
|
||||
if (double(nElmts_)/tableSize_ > 0.8 && tableSize_ < maxTableSize)
|
||||
@ -316,7 +316,7 @@ bool Foam::HashTable<T, Key, Hash>::set
|
||||
{
|
||||
// Found - overwrite existing entry
|
||||
// this corresponds to the Perl convention
|
||||
hashedEntry* ep = new hashedEntry(key, newEntry, existing->next_);
|
||||
hashedEntry* ep = new hashedEntry(key, obj, existing->next_);
|
||||
|
||||
// Replace existing element - within list or insert at the head
|
||||
if (prev)
|
||||
@ -450,15 +450,15 @@ Foam::label Foam::HashTable<T, Key, Hash>::erase
|
||||
const HashTable<AnyType, Key, AnyHash>& other
|
||||
)
|
||||
{
|
||||
// Remove other keys from this table
|
||||
const label nTotal = this->size();
|
||||
label changed = 0;
|
||||
|
||||
if (other.size() < nTotal)
|
||||
using other_iter =
|
||||
typename HashTable<AnyType, Key, AnyHash>::const_iterator;
|
||||
|
||||
if (other.size() <= nTotal)
|
||||
{
|
||||
// other is smaller, use its keys for removal
|
||||
using other_iter =
|
||||
typename HashTable<AnyType, Key, AnyHash>::const_iterator;
|
||||
// The other is smaller/same-size, use its keys for removal
|
||||
|
||||
for
|
||||
(
|
||||
@ -475,7 +475,7 @@ Foam::label Foam::HashTable<T, Key, Hash>::erase
|
||||
}
|
||||
else
|
||||
{
|
||||
// other is same/larger: iterate ourselves and check for key in other
|
||||
// We are smaller: remove if found in the other hash
|
||||
for
|
||||
(
|
||||
iterator iter = begin();
|
||||
@ -494,6 +494,39 @@ Foam::label Foam::HashTable<T, Key, Hash>::erase
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
template<class AnyType, class AnyHash>
|
||||
Foam::label Foam::HashTable<T, Key, Hash>::retain
|
||||
(
|
||||
const HashTable<AnyType, Key, AnyHash>& other
|
||||
)
|
||||
{
|
||||
const label nTotal = this->size();
|
||||
label changed = 0;
|
||||
|
||||
if (other.empty())
|
||||
{
|
||||
// Trivial case
|
||||
changed = nTotal;
|
||||
this->clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inverted logic: remove if *not* found in the other hash
|
||||
|
||||
for (iterator iter = begin(); iter != end(); ++iter)
|
||||
{
|
||||
if (!other.found(iter.key()) && erase(iter))
|
||||
{
|
||||
++changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
void Foam::HashTable<T, Key, Hash>::resize(const label sz)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@ Note
|
||||
SourceFiles
|
||||
HashTableI.H
|
||||
HashTable.C
|
||||
HashTableCoreI.H
|
||||
HashTableCore.C
|
||||
HashTableIO.C
|
||||
|
||||
@ -247,7 +248,7 @@ private:
|
||||
|
||||
//- Assign a new hash-entry to a possibly already existing key.
|
||||
// Return true if the new entry was set.
|
||||
bool set(const Key& key, const T& newEntry, const bool protect);
|
||||
bool set(const Key& key, const T& obj, const bool protect);
|
||||
|
||||
|
||||
protected:
|
||||
@ -307,17 +308,20 @@ public:
|
||||
//- Return true if the hash table is empty
|
||||
inline bool empty() const;
|
||||
|
||||
//- Return true if hashedEntry is found in table
|
||||
//- Return true if hashed entry is found in table
|
||||
bool found(const Key& key) const;
|
||||
|
||||
//- Find and return an iterator set at the hashedEntry
|
||||
//- Find and return an iterator set at the hashed entry
|
||||
// If not found iterator = end()
|
||||
iterator find(const Key& key);
|
||||
|
||||
//- Find and return an const_iterator set at the hashedEntry
|
||||
//- Find and return an const_iterator set at the hashed entry
|
||||
// If not found iterator = end()
|
||||
const_iterator find(const Key& key) const;
|
||||
|
||||
//- Return hashed entry if it exists, or return the given default
|
||||
inline const T& lookup(const Key& key, const T& deflt) const;
|
||||
|
||||
//- Return the table of contents
|
||||
List<Key> toc() const;
|
||||
|
||||
@ -327,42 +331,50 @@ public:
|
||||
|
||||
// Edit
|
||||
|
||||
//- Insert a new hashedEntry
|
||||
//- Insert a new entry
|
||||
// Return true if the entry inserted, which means that it did
|
||||
// not previously exist in the table.
|
||||
inline bool insert(const Key& key, const T& newEntry);
|
||||
inline bool insert(const Key& key, const T& obj);
|
||||
|
||||
//- Assign a new hashedEntry, overwriting existing entries.
|
||||
//- Assign a new entry, overwriting existing entries.
|
||||
// Returns true.
|
||||
inline bool set(const Key& key, const T& newEntry);
|
||||
inline bool set(const Key& key, const T& obj);
|
||||
|
||||
//- Erase a hashedEntry specified by given iterator
|
||||
//- Erase an entry specified by given iterator
|
||||
// This invalidates the iterator until the next ++ operation
|
||||
bool erase(const iterator& iter);
|
||||
|
||||
//- Erase a hashedEntry specified by the given key
|
||||
//- Erase an entry specified by the given key
|
||||
bool erase(const Key& key);
|
||||
|
||||
//- Remove entries given by the listed keys from this HashTable
|
||||
//- Remove table entries given by the listed keys
|
||||
// Return the number of elements removed
|
||||
label erase(const UList<Key>& keys);
|
||||
|
||||
//- Remove entries given by the listed keys from this HashTable
|
||||
//- Remove table entries given by the listed keys
|
||||
// Return the number of elements removed
|
||||
template<unsigned Size>
|
||||
label erase(const FixedList<Key, Size>& keys);
|
||||
|
||||
//- Remove entries given by the listed keys from this HashTable
|
||||
//- Remove table entries given by the listed keys
|
||||
// Return the number of elements removed
|
||||
label erase(std::initializer_list<Key> keys);
|
||||
|
||||
//- Remove entries given by the given keys from this HashTable
|
||||
//- Remove table entries given by keys of the other hash-table.
|
||||
// Return the number of elements removed.
|
||||
// The parameter HashTable needs the same type of key, but the
|
||||
//
|
||||
// The other hash-table must have the same type of key, but the
|
||||
// type of values held and the hashing function are arbitrary.
|
||||
template<class AnyType, class AnyHash>
|
||||
label erase(const HashTable<AnyType, Key, AnyHash>& other);
|
||||
|
||||
//- Retain table entries given by keys of the other hash-table.
|
||||
//
|
||||
// The other hash-table must have the same type of key, but the
|
||||
// type of values held and the hashing function are arbitrary.
|
||||
template<class AnyType, class AnyHash>
|
||||
label retain(const HashTable<AnyType, Key, AnyHash>& other);
|
||||
|
||||
//- Resize the hash table for efficiency
|
||||
void resize(const label sz);
|
||||
|
||||
@ -383,10 +395,10 @@ public:
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Find and return a hashedEntry
|
||||
//- Find and return a hashed entry. FatalError if it does not exist.
|
||||
inline T& operator[](const Key& key);
|
||||
|
||||
//- Find and return a hashedEntry
|
||||
//- Find and return a hashed entry. FatalError if it does not exist.
|
||||
inline const T& operator[](const Key& key) const;
|
||||
|
||||
//- Return existing entry or create a new entry.
|
||||
@ -394,6 +406,12 @@ public:
|
||||
// value-initialized. For primitives, this will be zero.
|
||||
inline T& operator()(const Key& key);
|
||||
|
||||
//- Return existing entry or insert a new entry.
|
||||
inline T& operator()(const Key& key, const T& deflt);
|
||||
|
||||
//- Return hashed entry if it exists, or return the given default
|
||||
inline const T& operator()(const Key& key, const T& deflt) const;
|
||||
|
||||
//- Assignment
|
||||
void operator=(const HashTable<T, Key, Hash>& rhs);
|
||||
|
||||
|
@ -79,10 +79,10 @@ template<class T, class Key, class Hash>
|
||||
inline bool Foam::HashTable<T, Key, Hash>::insert
|
||||
(
|
||||
const Key& key,
|
||||
const T& newEntry
|
||||
const T& obj
|
||||
)
|
||||
{
|
||||
return this->set(key, newEntry, true);
|
||||
return this->set(key, obj, true);
|
||||
}
|
||||
|
||||
|
||||
@ -90,10 +90,10 @@ template<class T, class Key, class Hash>
|
||||
inline bool Foam::HashTable<T, Key, Hash>::set
|
||||
(
|
||||
const Key& key,
|
||||
const T& newEntry
|
||||
const T& obj
|
||||
)
|
||||
{
|
||||
return this->set(key, newEntry, false);
|
||||
return this->set(key, obj, false);
|
||||
}
|
||||
|
||||
|
||||
@ -105,6 +105,18 @@ Foam::HashTable<T, Key, Hash>::xfer()
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const T& Foam::HashTable<T, Key, Hash>::lookup
|
||||
(
|
||||
const Key& key,
|
||||
const T& deflt
|
||||
) const
|
||||
{
|
||||
const_iterator iter = this->find(key);
|
||||
return iter.found() ? iter.object() : deflt;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
@ -156,6 +168,36 @@ inline T& Foam::HashTable<T, Key, Hash>::operator()(const Key& key)
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline T& Foam::HashTable<T, Key, Hash>::operator()
|
||||
(
|
||||
const Key& key,
|
||||
const T& deflt
|
||||
)
|
||||
{
|
||||
iterator iter = this->find(key);
|
||||
|
||||
if (iter.found())
|
||||
{
|
||||
return iter.object();
|
||||
}
|
||||
|
||||
this->insert(key, deflt);
|
||||
return find(key).object();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
inline const T& Foam::HashTable<T, Key, Hash>::operator()
|
||||
(
|
||||
const Key& key,
|
||||
const T& deflt
|
||||
) const
|
||||
{
|
||||
return this->lookup(key, deflt);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * iterator base * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
|
@ -203,7 +203,7 @@ template<class T, class Key, class Hash>
|
||||
bool Foam::StaticHashTable<T, Key, Hash>::set
|
||||
(
|
||||
const Key& key,
|
||||
const T& newEntry,
|
||||
const T& obj,
|
||||
const bool protect
|
||||
)
|
||||
{
|
||||
@ -229,7 +229,7 @@ bool Foam::StaticHashTable<T, Key, Hash>::set
|
||||
localObjects.setSize(existing+1);
|
||||
|
||||
localKeys[existing] = key;
|
||||
localObjects[existing] = newEntry;
|
||||
localObjects[existing] = obj;
|
||||
|
||||
nElmts_++;
|
||||
}
|
||||
@ -250,7 +250,7 @@ bool Foam::StaticHashTable<T, Key, Hash>::set
|
||||
{
|
||||
// Found - overwrite existing entry
|
||||
// this corresponds to the Perl convention
|
||||
objects_[hashIdx][existing] = newEntry;
|
||||
objects_[hashIdx][existing] = obj;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -121,10 +121,10 @@ class StaticHashTable
|
||||
|
||||
//- Return the hash index of the Key within the current table size.
|
||||
// No checks for zero-sized tables.
|
||||
inline label hashKeyIndex(const Key&) const;
|
||||
inline label hashKeyIndex(const Key& key) const;
|
||||
|
||||
//- Assign a new hashed entry to a possibly already existing key
|
||||
bool set(const Key&, const T& newElmt, bool protect);
|
||||
bool set(const Key& key, const T& obj, bool protect);
|
||||
|
||||
|
||||
public:
|
||||
|
@ -26,8 +26,6 @@ License
|
||||
#include "error.H"
|
||||
#include "IOstreams.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Classes * * * * * * * * * * * * //
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class Key, class Hash>
|
||||
@ -59,10 +57,10 @@ template<class T, class Key, class Hash>
|
||||
inline bool Foam::StaticHashTable<T, Key, Hash>::insert
|
||||
(
|
||||
const Key& key,
|
||||
const T& newEntry
|
||||
const T& obj
|
||||
)
|
||||
{
|
||||
return set(key, newEntry, true);
|
||||
return set(key, obj, true);
|
||||
}
|
||||
|
||||
|
||||
@ -70,10 +68,10 @@ template<class T, class Key, class Hash>
|
||||
inline bool Foam::StaticHashTable<T, Key, Hash>::set
|
||||
(
|
||||
const Key& key,
|
||||
const T& newEntry
|
||||
const T& obj
|
||||
)
|
||||
{
|
||||
return set(key, newEntry, false);
|
||||
return set(key, obj, false);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user