Commit 0a62fd2f authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: allow passing of comparator to sortToc methods

- this increases the flexibility of the interface

- Add stringOps 'natural' string sorting comparison.
  Digits are sorted in their natural order, which means that
      (file10.txt file05.txt file2.txt)
  are sorted as
      (file2.txt file05.txt file10.txt)

STYLE: consistent naming of template parameters for comparators

  - Compare for normal binary predicates
  - ListComparePredicate for list compare binary predicates
parent 8ec64d81
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -27,6 +27,8 @@ Description
#include "SortableList.H"
#include "ListOps.H"
#include "HashSet.H"
#include "stringOps.H"
using namespace Foam;
......@@ -175,6 +177,142 @@ int main(int argc, char *argv[])
Info<< "flat = " << values << endl;
}
// Sort strings
{
HashSet<string> hashed
{
"2.txt",
"05.txt",
"15.txt",
"other.bak04",
"other.bak1",
"file1.txt",
"file10.txt",
"file2.txt",
"file100.txt",
"file.txt",
"file011.txt",
"file15.txt",
"file0009.txt",
"abcd.txt",
// Some regular processor directories
"processor0",
"processor1",
"processor9",
"processor10",
"processor11",
"processor20",
"processor21",
"processor35",
"processors",
// Aggregate processor directories
"processor0-31",
"processor32-63",
"processor64-95",
"processor96-127",
"processor128-159",
"processor160-191",
"processor192-223",
"processor224-255",
};
Info<< nl << "Test string sorting" << nl << endl;
// Using hash toc
if (true)
{
Info<< "Unsorted" << hashed.toc() << endl;
Info<< "sortedToc" << hashed.sortedToc() << endl;
Info<< "natural"
<< hashed.sortedToc(stringOps::natural_sort()) << endl;
Info<< "reverse natural"
<< hashed.sortedToc(stringOps::natural_sort::reverse())
<< endl;
}
// Normal list
if (true)
{
labelList order;
List<string> strings(hashed.toc());
Info<< nl << "stringList:" << strings << endl;
sort(strings);
Info<< "normal sort:" << strings << endl;
shuffle(strings);
sort(strings, stringOps::natural_sort());
Info<< "natural sort:" << strings << endl;
shuffle(strings);
sort(strings, stringOps::natural_sort::reverse());
Info<< "reverse natural:" << strings << endl;
strings = hashed.toc();
Info<< nl << "test sorted order" << endl;
Info<< nl << "list:" << strings << endl;
sortedOrder(strings, order);
Info<< "sortedOrder:" << flatOutput(order) << endl;
shuffle(strings);
sort(strings, stringOps::natural_sort());
Info<< "reverse natural:" << strings << endl;
shuffle(strings);
sort(strings, stringOps::natural_sort::reverse());
Info<< "reverse natural:" << strings << endl;
sortedOrder
(
strings,
order,
stringOps::natural_sort::less<string>(strings)
);
Info<< "natural sortedOrder: " << flatOutput(order) << endl;
}
// SortableList
if (false)
{
SortableList<string> sortable;
Info<< nl << "Testing sortable list";
// Assign to ensure list is initially unsorted
sortable = hashed.toc();
Info<< nl << "input:" << sortable << endl;
sortable.sort();
Info<< nl << "normal:" << sortable << endl;
// This is still a bother (looks fairly ugly)
// so not implemented for now
/// // Assign to ensure list is initially unsorted
/// sortable = hashed.toc();
/// sortable.sort
/// (
/// stringOps::natural_sort::less<string>(sortable)
/// );
/// Info<< nl << "natural:" << sortable << endl;
/// // Assign to ensure list is initially unsorted
/// sortable = hashed.toc();
/// sortable.sort
/// (
/// stringOps::natural_sort::greater<string>(sortable)
/// );
/// Info<< nl << "natural:" << sortable << endl;
}
}
Info<< "\nEnd\n" << endl;
return 0;
......
......@@ -114,6 +114,7 @@ $(strings)/wordRe/wordRe.C
$(strings)/wordRes/wordRes.C
$(strings)/lists/hashedWordList.C
$(strings)/stringOps/stringOps.C
$(strings)/stringOps/stringOpsSort.C
$(strings)/parsing/parsing.C
ops = primitives/ops
......
......@@ -189,6 +189,17 @@ Foam::wordList Foam::DictionaryBase<IDLListType, T>::sortedToc() const
}
template<class IDLListType, class T>
template<class Compare>
Foam::wordList Foam::DictionaryBase<IDLListType, T>::sortedToc
(
const Compare& comp
) const
{
return hashedTs_.sortedToc(comp);
}
template<class IDLListType, class T>
void Foam::DictionaryBase<IDLListType, T>::insert(const word& keyword, T* tPtr)
{
......
......@@ -131,6 +131,10 @@ public:
//- Return the table of contents as a sorted list
wordList sortedToc() const;
//- Return table of contents sorted using the specified comparator
template<class Compare>
wordList sortedToc(const Compare& comp) const;
// Editing
......
......@@ -268,13 +268,27 @@ Foam::List<Key> Foam::HashTable<T, Key, Hash>::toc() const
template<class T, class Key, class Hash>
Foam::List<Key> Foam::HashTable<T, Key, Hash>::sortedToc() const
{
List<Key> keyLst = this->toc();
List<Key> keyLst(this->toc());
Foam::sort(keyLst);
return keyLst;
}
template<class T, class Key, class Hash>
template<class Compare>
Foam::List<Key> Foam::HashTable<T, Key, Hash>::sortedToc
(
const Compare& comp
) const
{
List<Key> keyLst(this->toc());
Foam::sort(keyLst, comp);
return keyLst;
}
template<class T, class Key, class Hash>
template<class UnaryPredicate>
Foam::List<Key> Foam::HashTable<T, Key, Hash>::tocKeys
......
......@@ -347,6 +347,10 @@ public:
//- Return the table of contents as a sorted list
List<Key> sortedToc() const;
//- Return table of contents sorted using the specified comparator
template<class Compare>
List<Key> sortedToc(const Compare& comp) const;
//- Return the sorted table of contents with keys that satisfy
// the unary predicate, optionally with inverted logic.
template<class UnaryPredicate>
......
......@@ -110,24 +110,44 @@ void inplaceMapKey(const labelUList& oldToNew, Container& lst);
template<class T>
void sortedOrder(const UList<T>& lst, labelList& order);
template<class T, class Cmp>
void sortedOrder(const UList<T>& lst, labelList& order, const Cmp& cmp);
//- Sort using specified list compare predicate
template<class T, class ListComparePredicate>
void sortedOrder
(
const UList<T>& lst,
labelList& order,
const ListComparePredicate& comp
);
//- Generate (sorted) indices corresponding to duplicate list values
template<class T>
void duplicateOrder(const UList<T>& lst, labelList& order);
template<class T, class Cmp>
void duplicateOrder(const UList<T>& lst, labelList& order, const Cmp& cmp);
//- Generate (sorted) indices corresponding to duplicate list values
// sort using specified list compare predicate
template<class T, class ListComparePredicate>
void duplicateOrder
(
const UList<T>& lst,
labelList& order,
const ListComparePredicate& comp
);
//- Generate (sorted) indices corresponding to unique list values
template<class T>
void uniqueOrder(const UList<T>& lst, labelList& order);
template<class T, class Cmp>
void uniqueOrder(const UList<T>& lst, labelList& order, const Cmp& cmp);
//- Generate (sorted) indices corresponding to unique list values
// sort using specified list compare predicate
template<class T, class ListComparePredicate>
void uniqueOrder
(
const UList<T>& lst,
labelList& order,
const ListComparePredicate& comp
);
//- Inplace sorting and removal of duplicates.
......@@ -137,8 +157,12 @@ void inplaceUniqueSort(ListType& lst);
//- Inplace sorting and removal of duplicates.
// Do not use FixedList for the input list, since it doesn't resize.
template<class ListType, class Cmp>
void inplaceUniqueSort(ListType& lst, const Cmp& cmp);
template<class ListType, class ListComparePredicate>
void inplaceUniqueSort
(
ListType& lst,
const ListComparePredicate& comp
);
//- Extract elements of List when select is a certain value.
......
......@@ -211,27 +211,30 @@ void Foam::sortedOrder
}
template<class T, class Cmp>
template<class T, class ListComparePredicate>
void Foam::sortedOrder
(
const UList<T>& lst,
labelList& order,
const Cmp& cmp
const ListComparePredicate& comp
)
{
const label len = lst.size();
// list lengths must be identical
if (order.size() != lst.size())
if (order.size() != len)
{
// avoid copying any elements, they are overwritten anyhow
// Avoid copying any elements, they are overwritten anyhow
order.clear();
order.setSize(lst.size());
order.setSize(len);
}
forAll(order, elemI)
for (label i=0; i<len; ++i)
{
order[elemI] = elemI;
order[i] = i; // identity
}
Foam::stableSort(order, cmp);
Foam::stableSort(order, comp);
}
......@@ -246,12 +249,12 @@ void Foam::duplicateOrder
}
template<class T, class Cmp>
template<class T, class ListComparePredicate>
void Foam::duplicateOrder
(
const UList<T>& lst,
labelList& order,
const Cmp& cmp
const ListComparePredicate& comp
)
{
if (lst.size() < 2)
......@@ -260,7 +263,7 @@ void Foam::duplicateOrder
return;
}
sortedOrder(lst, order, cmp);
sortedOrder(lst, order, comp);
const label last = (order.size()-1);
label n = 0;
......@@ -286,15 +289,15 @@ void Foam::uniqueOrder
}
template<class T, class Cmp>
template<class T, class ListComparePredicate>
void Foam::uniqueOrder
(
const UList<T>& lst,
labelList& order,
const Cmp& cmp
const ListComparePredicate& comp
)
{
sortedOrder(lst, order, cmp);
sortedOrder(lst, order, comp);
if (order.size() > 1)
{
......@@ -324,18 +327,24 @@ void Foam::inplaceUniqueSort(ListType& lst)
}
template<class ListType, class Cmp>
void Foam::inplaceUniqueSort(ListType& lst, const Cmp& cmp)
template<class ListType, class ListComparePredicate>
void Foam::inplaceUniqueSort
(
ListType& lst,
const ListComparePredicate& comp
)
{
labelList order;
uniqueOrder(lst, order, cmp);
uniqueOrder(lst, order, comp);
const label len = order.size();
ListType newLst(order.size());
newLst.setSize(order.size()); // Consistent sizing (eg, DynamicList)
ListType newLst(len);
newLst.setSize(len); // Consistent sizing (eg, DynamicList)
forAll(order, elemI)
for (label i=0; i<len; ++i)
{
newLst[elemI] = lst[order[elemI]];
newLst[i] = lst[order[i]];
}
lst.transfer(newLst);
......
......@@ -133,7 +133,7 @@ Foam::List<T>& Foam::SortableList<T>::shrink()
template<class T>
void Foam::SortableList<T>::sort()
{
sortedOrder(*this, indices_);
Foam::sortedOrder(*this, indices_);
List<T> lst(*this, indices_); // Copy with indices for mapping
List<T>::transfer(lst);
......@@ -143,7 +143,7 @@ void Foam::SortableList<T>::sort()
template<class T>
void Foam::SortableList<T>::reverseSort()
{
sortedOrder(*this, indices_, typename UList<T>::greater(*this));
Foam::sortedOrder(*this, indices_, typename UList<T>::greater(*this));
List<T> lst(*this, indices_); // Copy with indices for mapping
List<T>::transfer(lst);
......@@ -157,6 +157,7 @@ void Foam::SortableList<T>::swap(SortableList<T>& lst)
indices_.swap(lst.indices_);
}
template<class T>
Foam::Xfer<Foam::List<T>> Foam::SortableList<T>::xfer()
{
......
......@@ -119,8 +119,8 @@ public:
//- Clear the indices and return a reference to the underlying List
List<T>& shrink();
//- (stable) sort the list (if changed after construction time)
// also resizes the indices as required
//- (stable) sort the list (if changed after construction time).
// Resizes the indices as required
void sort();
//- Reverse (stable) sort the list
......
......@@ -293,10 +293,10 @@ void Foam::sort(UList<T>& a)
}
template<class T, class Cmp>
void Foam::sort(UList<T>& a, const Cmp& cmp)
template<class T, class Compare>
void Foam::sort(UList<T>& a, const Compare& comp)
{
std::sort(a.begin(), a.end(), cmp);
std::sort(a.begin(), a.end(), comp);
}
......@@ -307,10 +307,10 @@ void Foam::stableSort(UList<T>& a)
}
template<class T, class Cmp>
void Foam::stableSort(UList<T>& a, const Cmp& cmp)
template<class T, class Compare>
void Foam::stableSort(UList<T>& a, const Compare& comp)
{
std::stable_sort(a.begin(), a.end(), cmp);
std::stable_sort(a.begin(), a.end(), comp);
}
......
......@@ -139,39 +139,35 @@ public:
// Public classes
//- Less function class that can be used for sorting
class less
//- A list compare binary predicate for normal sort
struct less
{
const UList<T>& values_;
const UList<T>& values;
public:
less(const UList<T>& values)
less(const UList<T>& list)
:
values_(values)
values(list)
{}
bool operator()(const label a, const label b)
bool operator()(const label a, const label b) const
{
return values_[a] < values_[b];
return values[a] < values[b];
}
};
//- Greater function class that can be used for sorting
class greater
//- A list compare binary predicate for reverse sort
struct greater
{
const UList<T>& values_;
public:
const UList<T>& values;
greater(const UList<T>& values)
greater(const UList<T>& list)
:
values_(values)
values(list)
{}
bool operator()(const label a, const label b)
bool operator()(const label a, const label b) const
{
return values_[a] > values_[b];
return values[a] > values[b];
}
};
......@@ -487,14 +483,14 @@ public:
template<class T>
void sort(UList<T>& a);
template<class T, class Cmp>
void sort(UList<T>& a, const Cmp& cmp);
template<class T, class Compare>
void sort(UList<T>& a, const Compare& comp);
template<class T>
void stableSort(UList<T>& a);
template<class T, class Cmp>
void stableSort(UList<T>& a, const Cmp& cmp);
template<class T, class Compare>
void stableSort(UList<T>& a, const Compare& comp);
template<class T>
void shuffle(UList<T>& a);
......
......@@ -452,6 +452,10 @@ public:
//- Return the sorted table of contents
wordList sortedToc() const;
//- Return table of contents sorted using the specified comparator
template<class Compare>
wordList sortedToc(const Compare& comp) const;
//- Return the list of available keys or patterns
List<keyType> keys(bool patterns = false) const;
......
......@@ -28,6 +28,13 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Compare>
Foam::wordList Foam::dictionary::sortedToc(const Compare& comp) const
{
return hashedEntries_.sortedToc(comp);
}
template<class T>
T Foam::dictionary::lookupType
(
......
......@@ -49,37 +49,40 @@ namespace predicates
Class always Declaration
\*---------------------------------------------------------------------------*/
//- Unary and binary predicates returning true, useful for templating.
class always
//- Unary and binary predicates that always return true, useful for templating.
struct always
{
public:
typedef always value_type;