CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4

Threaded View

  1. #1
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    [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:

    Code:
    // 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
    {
    public:
      RegexPredicate(String ^strRegex, RegexOptions opt) : m_regex(gcnew Regex(strRegex, opt))
      {
        m_pred = gcnew Predicate<String ^>(this, &RegexPredicate::PredFunc);
      }
    
      initonly Predicate<String ^> ^m_pred;
    
    private:
      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();
        Console::WriteLine("Hit enter to continue...");
        Console::ReadLine();
    #endif
        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("*", ".*"), "$"),
        RegexOptions::IgnoreCase);
    
      // 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(astrFilteredFileNames[i]);
      Console::WriteLine();
      Console::WriteLine("{0} out of {1} files matched the predicate", astrFilteredFileNames->Length, astrFileNames->Length);
    
    #ifdef _DEBUG
      Console::WriteLine();
      Console::WriteLine("Hit enter to continue...");
      Console::ReadLine();
    #endif
      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 7th, 2011 at 11:04 PM. 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
  •  





Click Here to Expand Forum to Full Width

Featured