[RESOLVED] Filtering array items according to a dynamically created predicate
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4

Thread: [RESOLVED] Filtering array items according to a dynamically created predicate

Threaded View

  1. #1
    Join Date
    Jun 2010

    [RESOLVED] Filtering array items according to a dynamically created predicate

    I just encountered the requirement to filter array items according to a dynamically created predicate, i.e. one determined by user input. I didn't find anything really enlightening on MSDN (the sample on Array::FindAll<T> only demonstrates hard-coded predicates) or CodeGuru, so I rolled my own. It involves an extra class created for the sole purpose of representing the predicate. It goes something like this:

    // Test1.cpp: Hauptprojektdatei.
    #include "stdafx.h"
    using namespace System;
    using namespace System::IO;
    using namespace System::Text::RegularExpressions;
    // Regular expression predicate class
    public ref class RegexPredicate
      RegexPredicate(String ^strRegex, RegexOptions opt) : m_regex(gcnew Regex(strRegex, opt))
        m_pred = gcnew Predicate<String ^>(this, &RegexPredicate::PredFunc);
      initonly Predicate<String ^> ^m_pred;
      bool PredFunc(String ^s)
        return m_regex->IsMatch(s);
      initonly Regex ^m_regex;
    int main(array<System::String ^> ^args)
      if (args->Length != 1) {
        Console::WriteLine("Usage: Invoke this program with a dir-style file name match pattern as the only\n"
          "command line argument");
    #ifdef _DEBUG
        Console::WriteLine("Hit enter to continue...");
        return 1;
      // Build an array of all file names without absolute path
      array<FileInfo ^> ^afi = (gcnew DirectoryInfo("."))->GetFiles();
      array<String ^> ^astrFileNames = gcnew array<String ^>(afi->Length);
      for (int i = 0; i < afi->Length; ++i)
        astrFileNames[i] = afi[i]->Name;
      // Construct regex predicate object based on the dir-style wildcard pattern converted to a regex
      RegexPredicate ^rxp =
        gcnew RegexPredicate(String::Concat("^", args[0]->Replace(".", "\\.")->Replace("?", ".?")->Replace("*", ".*"), "$"),
      // Filter the file names according to the predicate
      array<String ^> ^astrFilteredFileNames = Array::FindAll(astrFileNames, rxp->m_pred);
      // List the filtered file names
      for (int i = 0; i < astrFilteredFileNames->Length; ++i)
      Console::WriteLine("{0} out of {1} files matched the predicate", astrFilteredFileNames->Length, astrFileNames->Length);
    #ifdef _DEBUG
      Console::WriteLine("Hit enter to continue...");
      return 0;
    You can see, the predicate class holds the raw predicate (i.e. the delegate) and the predicate function, along with the data needed to determine the match. It works like a charm and is nicely encapsulated, however, since this certainly is something that's required in a vast lot of programs, I wonder whether there is any more straightforward and/or elegant way to achieve this.

    Of course the above code is just a demo program. Even my XP already has a dir command and the classes in the System::IO namespace do a good job filtering file names as well. This is just a model of what I need to do (and am currently doing that way) in another app.

    Any comments are welcome.
    Last edited by Eri523; May 8th, 2011 at 12:04 AM. Reason: Fixed a comment in the code
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Windows Mobile Development Center

Click Here to Expand Forum to Full Width

This is a Codeguru.com survey!

HTML5 Development Center