C# What is the speediest technique for IsStringMadeOf method?

I have a method which is called thousands of times, but it is currently very slow to run. Is there a better technique? Unsafe methods are allowed.

It simply checks letters of input string whether it could be made of the letters of other string, like an anagram checker.

This is what my method currently looks like.

public static bool IsStringMadeOf(this string str, string from)
{
    for (int i = 0; i < str.Length; i++)
    {
        int index = from.IndexOf(str[i]);
        if (index != -1)
        {
            from = from.Remove(index, 1);
        }
        else
        {
            return false;
        }
    }
    return true;
}

For my test cases, the results should be as follows:

str    | from        | result
-------------------------------
SLOW   | WSOL        | true
SLOW   | WTOL        | false
ASIA   | XZYABSTRIB  | false
ASIA   | XZYABSTRIAB | true
Jon Skeet
people
quotationmark

To start with, you've got a lot of string operations here - you're creating lots of new strings by removing a single character each time, and you're using IndexOf a lot too.

I would start very simply - just sort the characters in each string, and then see if the sequences are equal:

public static bool IsStringMadeOf(this string str, string from)
{
    if (str.Length != from.Length)
    {
        return false;
    }
    char[] strArray = str.ToCharArray();
    char[] fromArray = from.ToCharArray();
    Array.Sort(strArray);
    Array.Sort(fromArray);
    for (int i = 0; i < strArray.Length; i++)
    {
        if (strArray[i] != fromArray[i])
        {
            return false;
        }
    }
    return true;
}

That will certainly help a lot if you have long strings. For short strings, the creation of the char arrays may end up dominating... but that's at least what I'd try to start with.

Note that the above is a slightly optimized form of this LINQ version:

public static bool IsStringMadeOf(this string str, string from)
{
    if (str.Length != from.Length)
    {
        return false;
    }
    return str.OrderBy(c => c).SequenceEqual(from.OrderBy(c => c));
}

people

See more on this question at Stackoverflow