tags:

views:

323

answers:

3

I have a string such as "big bad dog", how can I get an string[] array which includes all the possible word/phrase combinations?

So, I would like to return "big", "bad", "dog", "big bad", "bad dog" and "big bad dog" - therefore the order of the words in the original string must be respected.

Is this something that could be done with a regular expression?

+5  A: 
string[] array = new string[]{"big", "bad", "dog"};
for(ulong mask = 0; mask < (1ul << array.Length); mask++)
{
    string permutation = "";
    for(int i = 0; i < array.Length;  i++)
    {
        if((mask & (1ul << (array.Length - 1 - i))) != 0)
        {
            permutation += array[i] + " ";
        }
    }
    Console.WriteLine(permutation);
}

EDIT: No, it can not be done using only a single regular expression.

EDIT: Per Eric Lippert, change masks to ulong (UInt64).

Matthew Flaschen
This solves the problem but doesn't fully answer the OPs question.
Jeff Yates
And what if there are more than 32 words? (I know, it'll take a while to get through the first four billion, but machines are fast these days.)
Eric Lippert
A: 

What about splitting the string into array of separate words

string str = "big fat dog";
string[] words = str.Split(new Char[] { ' ', ',', '.', ':', '\t' });

and then you can use this to make word combinations

string[] words = new string[]{"big", "bad", "dog"}; 
for(int mask = 0; mask < 1 << (words.Length); mask++) 
{ 
  string permutation = ""; 
  for(int i = 0; i < words.Length;  i++) 
  { 
    if((mask & (1 << (words.Length - 1 - i))) != 0) 
    { 
      permutation += words[i] + " "; 
    } 
  } 
  Console.WriteLine(permutation); 
}

I think regular expresion has no use here.

Machta
This solves the problem but doesn't fully answer the OPs question.
Jeff Yates
It doesn't? Please, can I leave it like this, Mrs teacher?
Machta
+4  A: 

I think this is a nice problem to solve recursively. My take:

public static String[] findWords(params string[] args)
{

        if (args.Count() == 0)
        {
            return new String[] { "" };
        }
        else
        {
            String[] oldWords = findWords(args.Skip(1).ToArray());
            String[] newWords = oldWords.Where(word => word == "" || word.Split(new String[] { " " }, StringSplitOptions.RemoveEmptyEntries)[0] == args[1])
                                        .Select(word => (args[0] + " " + word).Trim()).ToArray();

            return oldWords.Union(newWords).ToArray();
        }
} 

A findWords("big", "bad", "dog") returns your list of phrases.

Edit: Edited to only include consecutive phrases.

Jens
This solves the problem but doesn't fully answer the OPs question.
Jeff Yates
True, sorry. I promise to read better in the future =)
Jens
Thanks Jens, this is pretty much what i wanted. Only one small problem (which i didn't explain in my original post) and that is I only want consecutive words or phrases so "big dog" should not be a match. Is there a tweak you can make to your code?
Stuart
@Stuart: Edited. It looses elegance, though =)
Jens
Hi @Jen, that's great. Thanks a lot. Hopefully my gratitude will make up in some small way for the loss of elegance of your code! :)
Stuart