views:

79

answers:

3

I have a list:

Dim list As New List(Of String)

with the following items:

290-7-11

1255-7-12

222-7-11

290-7-13

What's an easy and fast way to search if duplicate of "first block" plus "-" plus "second block" is already in the list. Example the item 290-7 appears twice, 290-7-11 and 290-7-13.

I am using .net 2.0

A: 

Do you want to stop user from adding it?
If so, a HashTable with the key as first block-second block could be of use.

If not, LINQ is the way to go.
But, it will have to traverse the list to check.
How big can this list be?

EDIT: I don't know if HashTable has generic version.
You could also use SortedDictionary which can take generic arguments.

shahkalpesh
this list is not that big, 100 items max. I am using .net 2.0
Saif Khan
yes. I waant to stop the user from adding it.
Saif Khan
Don't worry about it then. Searching 100 items won't be a pain.
shahkalpesh
+4  A: 

If you only want to know if there are duplicates but don't care what they are...

The easiest way (assuming exactly two dashes).

Boolean hasDuplicatePrefixes = list
    .GroupBy(i => i.Substring(0, i.LastIndexOf('-')))
    .Any(g => g.Count() > 1)

The fastest way (at least for large sets of strings).

HashSet<String> hashSet = new HashSet<String>();

Boolean hasDuplicatePrefixes = false;
foreach (String item in list)
{
    String prefix = item.Substring(0, item.LastIndexOf('-'));

    if (hashSet.Contains(prefix))
    {
        hasDuplicatePrefixes = true;
        break;
    }
    else
    {
        hashSet.Add(prefix);
    }
}

If there are cases with more than two dashes, use the following. This will still fail with a single dash.

String prefix = item.Substring(0, item.IndexOf('-', item.IndexOf('-') + 1));

In .NET 2.0 use Dictionary<TKey, TValue> instead of HashSet<T>.

Dictionary<String, Boolean> dictionary= new Dictionary<String, Boolean>();

Boolean hasDuplicatePrefixes = false;
foreach (String item in list)
{
    String prefix = item.Substring(0, item.LastIndexOf('-'));

    if (dictionary.ContainsKey(prefix))
    {
        hasDuplicatePrefixes = true;
        break;
    }
    else
    {
        dictionary.Add(prefix, true);
    }
}

If you don't care about readability and speed, use an array instead of a list, and you are a real fan of regular expressions, you can do the following, too.

Boolean hasDuplicatePrefixes = Regex.IsMatch(
    String.Join("#", list), @".*(?:^|#)([0-9]+-[0-9]+-).*#\1");
Daniel Brückner
V.good. Code certainly helps.
shahkalpesh
HashSet? which ver of .net has it?
shahkalpesh
HashSet is 3.5+
Mehrdad Afshari
HashSet is 3.5 ... use Dictionary<TKey, TValue> in 2.0.
Daniel Brückner
A: 

If you're list contains only strings, then you can simply make a method that takes the string you want to find along with the list:

Boolean isStringDuplicated(String find, List<String> list)
{
    if (list == null)
        throw new System.ArgumentNullException("Given list is null.");

    int count = 0;

    foreach (String s in list)
    {
        if (s.Contains(find))
            count += 1;

        if (count == 2)
            return true;
    }

    return false;
}

If you're numbers have a special significance in your program, don't be afraid to use a class to represent them instead of sticking with strings. Then you would have a place to write all the custom functionality you want for said numbers.

King_Jester