Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the micro-optimal and most elegant way of returning List<string> of elements that occurs only once in other List<string>

Tags:

c#

.net

algorithm

This was an interview question I had today:

"Given a list of strings, return a list of only the unique strings"

I'm curious about what the Skeet-certified answer would be.

My own answer was

public static List<string> sans_repeats ( List<string> input ) 
{
    Dictoinary<string,int> counter = new Dictionary<string,int>();
    List<string> output = new List<string>();
    foreach ( string S in input ) 
    {
       if ( counter.HasKey(S) ) counter[S] = 1;
       else ++count[S];
    }     
    foreach ( KeyValuePair<string,int> entry in counter ) 
       if ( entry.Value == 1 ) output.Add(entry.Key);
    return output;
}

and interview said

"Well, that's one way to do it ..."

in a voice that sounded condescending, as if I was doing something wrong.

  • Is there anything logically wrong about it?
  • Is there a way to achieve a more memory- and processing-efficient solution?
  • Was the interviewer likely looking for a LINQ-esque solution? Why didn't he seem to like mine?
  • Is there a way to make this more compact?
like image 691
user5572578 Avatar asked Dec 19 '22 21:12

user5572578


2 Answers

Based on updated question, here's a way with LINQ:

var src = new List<string>() { "dog", "cat", "elephant", "dog", "dog" } ;
src.GroupBy(x => x).Where(y => y.Count() == 1).ToList();

Demo

like image 78
shree.pat18 Avatar answered Jan 19 '23 00:01

shree.pat18


Simplest way, use the in-built function:

List<string> distinctList = input.Distinct();

https://msdn.microsoft.com/library/bb920306(v=vs.90).aspx

Alternatively, check if the current item already exists in the output list and continue if it does:

List<string> output = new List<string>();
foreach (string S in input) 
{
    if (output.Contains(S)) continue;       
    output.Add(S);
}

Edit

Based on your comment that you only want items that occur once only:

Dictionary<string, int> stringCount = new Dictionary<string, int>();
foreach (string S in input) 
{
    if (stringCount.ContainsKey(S))
    {
        stringCount[S]++;
    }
    else
    {
        stringCount.Add(S, 1);
    }       
}

var output = stringCount.Where(x => x.Value == 1).ToList();
like image 41
Steve Avatar answered Jan 19 '23 00:01

Steve