简体   繁体   中英

Is there a faster method than looking through an array of strings for a string?

Currently I am doing this:

        List<int> ID = new List<int>();
        int a = 0;
        string[] findWordHere = ...
        string[] findOtherWordHere = ...
        string word = "this";
        string otherWord = "that";

        foreach (string word in findWordHere)
        {
            foreach (string otherWord in findOtherWordHere)
            {
                if (word == otherWord)
                {
                    ID.Add(a + 1);
                }
            }
            a++;
        }

This is very time consuming. Is there a better way to do this, say with linq?

Yes, there is. Add all items from the findOtherWordHere to HashSet<string> before the first loop, and use it for the lookup, like this:

ISet<string> lookup = new HashSet<string>(findOtherWordHere);
foreach (string word in findWordHere)
{
    if (lookup.Contains(word))
    {
        ID.Add(a + 1);
    }
    a++;
}

This runs in time proportional to the sum of lengths of findWordHere and findOtherWordHere , because HashSet<string> is built in linear time, and provides constant-time lookup capabilities.

Your original approach, on the other hand, runs in time proportional to the product of lengths of findWordHere and findOtherWordHere , because the worst case executes an inner loop to completion in each iteration of the outer loop.

You can use a HashSet<string> :

var set = new HashSet<string>(findOtherWordHere);
var IDs = findWordHere
            .Select((w,i) => new {w,i})
            .Where(p => set.Contains(p.w))
            .Select(p => p.i)
            .ToList();

This provides the indexes of the words contained in the other list, without loops and with reasonable performance.

If you don't need arrays you can use StringComparison method:

            List<int> ID = new List<int>();

            int a = 0;

            string root = "that";
            string root2 = "that";

            bool result = root.Equals(root2, StringComparison.Ordinal);


            if (result)
            {
               ID.Add(a + 1);
            }

Or if you want to ignore case use OrdinalIgnoreCase keep in mind ordinal is the fastest way to compare two strings:

        List<int> ID = new List<int>();

        int a = 0;

        string root = "that";
        string root2 = "that";

        bool result = root.Equals(root2, StringComparison.OrdinalIgnoreCase);


        if (result)
        {
           ID.Add(a + 1);
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM