ENH: add ListOps find/found accepting a unary predicate (#1182)

- can also be used for other purposes.
  Eg,

      if (ListOps::found(list, matcher))
      {
         ...
      }

  vs.

      if (!findStrings(matcher, list).empty())
      {
         ...
      }
This commit is contained in:
Mark Olesen
2019-01-25 11:45:03 +01:00
parent 5ec44cd51f
commit 87523acad3
9 changed files with 114 additions and 21 deletions

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2012-2013 OpenFOAM Foundation \\ / A nd | Copyright (C) 2012-2013 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2019 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -32,6 +32,8 @@ Description
#include "List.H" #include "List.H"
#include "SubList.H" #include "SubList.H"
#include "ListOps.H" #include "ListOps.H"
#include "labelField.H"
#include "MinMax.H"
#include "face.H" #include "face.H"
using namespace Foam; using namespace Foam;
@ -113,23 +115,41 @@ int main(int argc, char *argv[])
Info<< nl << "Test lambda predicates:" << nl << endl; Info<< nl << "Test lambda predicates:" << nl << endl;
List<label> test6(identity(11)); List<label> test6(identity(11, -4));
// shift range for general testing
std::for_each(test6.begin(), test6.end(), [](label& x){ x -= 4; });
Info<< "Subset of non-zero, even values: " // Add multiplier for mpore interesting testing
<< subsetList std::for_each(test6.begin(), test6.end(), [](label& x){ x *= 3; });
(
test6,
[](const label& x){ return x && !(x % 2); }
) << nl
<< endl;
test6.append(identity(13));
// Randomize the list // Randomize the list
std::random_shuffle(test6.begin(), test6.end()); std::random_shuffle(test6.begin(), test6.end());
Info<< "randomized input list: " << flatOutput(test6) << nl;
const auto evenNonZero = [](const label& x){ return x && !(x % 2); };
Info<< "location of first even/non-zero: "
<< ListOps::find(test6, evenNonZero) << nl;
Info<< "find > 12 && divisible by 5 : "
<< ListOps::find
(
test6,
[](const label& x) { return x > 12 && !(x % 5); }
) << nl;
Info<< "Found >= 8 : "
<< ListOps::found(test6, labelMinMax(8, labelMax)) << nl;
Info<< "Found >= 25 : "
<< ListOps::found(test6, labelMinMax(25, labelMax)) << nl;
Info<< "Subset of non-zero, even values: "
<< subsetList(test6, evenNonZero) << nl
<< endl;
test6.append(identity(13, 12));
Info<< "Randomized: " << flatOutput(test6) << endl; Info<< "Randomized: " << flatOutput(test6) << endl;
inplaceUniqueSort(test6); inplaceUniqueSort(test6);
Info<< "Unique : " << flatOutput(test6) << endl; Info<< "Unique : " << flatOutput(test6) << endl;

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2019 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -26,6 +26,7 @@ Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "stringListOps.H" #include "stringListOps.H"
#include "ListOps.H"
#include "FlatOutput.H" #include "FlatOutput.H"
#include "IOstreams.H" #include "IOstreams.H"
#include "StringStream.H" #include "StringStream.H"
@ -57,10 +58,18 @@ int main(int argc, char *argv[])
labelList matches = findStrings(regExp(".*ee.*"), strLst); labelList matches = findStrings(regExp(".*ee.*"), strLst);
Info<< "matches found for regexp .*ee.* :" << nl << matches << nl; Info<< "matches found for regexp .*ee.* :" << nl << matches << nl;
forAll(matches, i) forAll(matches, i)
{ {
Info<< " -> " << strLst[matches[i]] << nl; Info<< " -> " << strLst[matches[i]] << nl;
} }
Info<< "Match found using ListOps = "
<< ListOps::found(strLst, regExp(".*ee.*")) << nl;
Info<< "First index = "
<< ListOps::find(strLst, regExp(".*ee.*")) << nl;
Info<< endl; Info<< endl;
matches = findStrings(reLst, strLst); matches = findStrings(reLst, strLst);

View File

@ -582,6 +582,32 @@ struct greater
}; };
//- Find index of the first occurrence that satisfies the predicate.
// When start is specified, any occurrences before start are ignored.
// Linear search.
// \return position in list or -1 if not found.
template<class ListType, class UnaryPredicate>
label find
(
const ListType& input,
const UnaryPredicate& pred,
const label start=0
);
//- True if there is a value in the list that satisfies the predicate.
// When start is specified, any occurences before start are ignored.
// Linear search.
// \return true if found.
template<class ListType, class UnaryPredicate>
bool found
(
const ListType& input,
const UnaryPredicate& pred,
const label start=0
);
//- Set various locations of the list with a specified value. //- Set various locations of the list with a specified value.
// //
// \param list the list to modify // \param list the list to modify

View File

@ -1097,6 +1097,43 @@ void Foam::ListOps::uniqueEqOp<T>::operator()
} }
template<class ListType, class UnaryPredicate>
Foam::label Foam::ListOps::find
(
const ListType& input,
const UnaryPredicate& pred,
const label start
)
{
const label len = input.size();
if (start >= 0)
{
for (label i = start; i < len; ++i)
{
if (pred(input[i]))
{
return i;
}
}
}
return -1;
}
template<class ListType, class UnaryPredicate>
bool Foam::ListOps::found
(
const ListType& input,
const UnaryPredicate& pred,
const label start
)
{
return (ListOps::find(input, pred, start) >= 0);
}
template<class T> template<class T>
void Foam::ListOps::setValue void Foam::ListOps::setValue
( (

View File

@ -111,6 +111,7 @@ namespace Foam
template<class T> class MinMax; template<class T> class MinMax;
// Common min/max types // Common min/max types
typedef MinMax<label> labelMinMax;
typedef MinMax<scalar> scalarMinMax; typedef MinMax<scalar> scalarMinMax;

View File

@ -425,7 +425,7 @@ Foam::label Foam::voxelMeshSearch::findCell(const point& p) const
label nei = mesh_.faceNeighbour()[facei]; label nei = mesh_.faceNeighbour()[facei];
nextCell = (own == celli ? nei : own); nextCell = (own == celli ? nei : own);
if (findIndex(track_, nextCell, startOfTrack) != -1) if (track_.found(nextCell, startOfTrack))
{ {
return celli; return celli;
} }
@ -438,7 +438,7 @@ Foam::label Foam::voxelMeshSearch::findCell(const point& p) const
{ {
return nextCell; return nextCell;
} }
else if (findIndex(track_, nextCell, startOfTrack) != -1) else if (track_.found(nextCell, startOfTrack))
{ {
return -1; // point is really out return -1; // point is really out
} }

View File

@ -26,8 +26,8 @@ License
#include "sampledSets.H" #include "sampledSets.H"
#include "volFields.H" #include "volFields.H"
#include "IOobjectList.H" #include "IOobjectList.H"
#include "stringListOps.H"
#include "UIndirectList.H" #include "UIndirectList.H"
#include "ListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -69,7 +69,7 @@ Foam::label Foam::sampledSets::classifyFields()
// Detect missing fields // Detect missing fields
forAll(fieldSelection_, i) forAll(fieldSelection_, i)
{ {
if (findStrings(fieldSelection_[i], allFields).empty()) if (!ListOps::found(allFields, fieldSelection_[i]))
{ {
missed.append(i); missed.append(i);
} }

View File

@ -25,8 +25,8 @@ License
#include "sampledSurfaces.H" #include "sampledSurfaces.H"
#include "IOobjectList.H" #include "IOobjectList.H"
#include "stringListOps.H"
#include "UIndirectList.H" #include "UIndirectList.H"
#include "ListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -57,7 +57,7 @@ Foam::label Foam::sampledSurfaces::classifyFields()
// Detect missing fields // Detect missing fields
forAll(fieldSelection_, i) forAll(fieldSelection_, i)
{ {
if (findStrings(fieldSelection_[i], allFields).empty()) if (!ListOps::found(allFields, fieldSelection_[i]))
{ {
missed.append(i); missed.append(i);
} }

View File

@ -641,7 +641,7 @@ void Foam::isoSurfaceTopo::generateTriPoints
forAll(f1, fp) forAll(f1, fp)
{ {
oppositeI = f1[fp]; oppositeI = f1[fp];
if (findIndex(f0, oppositeI) == -1) if (!f0.found(oppositeI))
{ {
break; break;
} }