1

Could anyone tell me what's wrong in my code? Basically I need to add only the unique words from words1 to uniques list, after I compare both words1 and words2. In the if statement, if i remove ! then it finds the matching words (opposite of what i need)

    List<string> Unique(string lines1 ,string lines2,  char[] separators)
    {
        string[] words1 = lines1.Split(separators, StringSplitOptions.RemoveEmptyEntries);
        string[] words2 = lines2.Split(separators, StringSplitOptions.RemoveEmptyEntries);
        List<string> uniques = new List<string>();

        for (int i = 0; i < words1.Length; i++)
        {
            bool match;
            for (int x = 0; x < words2.Length; x++)
            {
                if (!words1[i].Equals(words2[x]))
                {
                    match = true;
                    uniques.Add(words1[i]);
                    break;
                }
                else
                {
                    match = false;
                }
            }
        }

        return uniques;
    }
Taher A. Ghaleb
  • 5,120
  • 5
  • 31
  • 44
Dom
  • 25
  • 4
  • As soon as you find a mismatch, you mark it as unique even when it did match before. You have to check *all* words, and only when *nothing* matched, is it unique – Hans Kesting Nov 24 '18 at 19:06
  • I guess you're doing this as a learning excercise - otherwise you could use Linq and do `var uniques = words1.Except(words2).ToList();` – Matthew Watson Nov 24 '18 at 19:17
  • If landed on this questions and you actually need "items from the list that are not in another list" - https://stackoverflow.com/questions/3944803/use-linq-to-get-items-in-one-list-that-are-not-in-another-list – Alexei Levenkov Nov 24 '18 at 19:50

2 Answers2

5

You could do minor changes to your loop

    for (int i = 0; i < words1.Length; i++)
    {
        bool match=false;
        for (int x = 0; x < words2.Length; x++)
        {
            if (words1[i].Equals(words2[x]))
            {
                match = true;
                break;
            }

        }
        if(!match && uniques.Contains(words1[i]))
        { 
            uniques.Add(words1[i]);
        }
        { 
        uniques.Add(words1[i]);
        }
    }

To make your code even shorter, you could use LINQ

List<string> Unique(string lines1 ,string lines2,  char[] separators)
{    
string[] words1 = lines1.Split(separators, StringSplitOptions.RemoveEmptyEntries);
string[] words2 = lines2.Split(separators, StringSplitOptions.RemoveEmptyEntries);
return words1.Except(words2).ToList();
}
Anu Viswan
  • 17,797
  • 2
  • 22
  • 51
  • Don't know LINQ yet, but your edit of my code worked! Thank you very much! – Dom Nov 24 '18 at 19:25
  • Note that this code does not add "unique" words obviously - `words1 = {"foo","foo","foo"}, words2={"bar"}` will result in `{"foo","foo","foo"}` which is unlikely to be called list of unique words by the most people... – Alexei Levenkov Nov 24 '18 at 19:49
  • @AlexeiLevenkov, updated with check for unique in existing list :) – Anu Viswan Nov 24 '18 at 20:04
0

Using two nested loops has a bad performance of O(n2). Use a set Union

return words1
    .Union(words2)
    .ToList();
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • Using `OrderBy` has a bad performance of O(n log n) (very unclear why you've added one). Question seem to be about either implementing `Except` or `Distinct` (not sure how `Union` fits into what OP asked). – Alexei Levenkov Nov 24 '18 at 20:04
  • As i understood the OP wants to combine both word lists by eliminating duplicates. [`Union`](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.union?view=netframework-4.7.2) performs a set union, i.e., it removes duplicates. I removed the `OrderBy`, but O(n log n) is much better than O(n^2). – Olivier Jacot-Descombes Nov 24 '18 at 20:08