Saif Khan
Saif Khan

Reputation: 18782

searching a list object

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

Upvotes: 0

Views: 237

Answers (3)

Daniel Brückner
Daniel Brückner

Reputation: 59645

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");

Upvotes: 4

lillicoder
lillicoder

Reputation: 552

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.

Upvotes: 0

shahkalpesh
shahkalpesh

Reputation: 33476

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.

Upvotes: 0

Related Questions