• akatherder (cs)

    So now it's bad form to rely on an exception in your standard code path? Picky picky.

  • Chnoodzen (unregistered)

    How about just letting the values overwrite each other

    foreach(string s in strObj){ UniqueHT[s] = "My CAPTCHA: craaazy"; }

  • Lastchance (cs)

    Ah, the old "use exception handling for non-exceptional logic" trick. That's the third time this week!

    Yes, I just got my "Get Smart" DVD set.

  • KattMan (cs)

    This is so enterprisey I might spring this on my co-workers. I mean it has arbitrarily adding values to an array, Exceptions used for standard processing, and recursion.

    Who wouldn't like this solution?

  • DOA (unregistered)

    To get a bit biblical... He who has never used exceptions in this manner, cast the first stone

    captcha: Noone gives a rat's ass

  • guy (unregistered)

    This person was probably translating VB6 code. I believe in VB6 collections did not have .contains, and using On Error Resume Next and checking the error number was the only way to check if the collection had a given key.

    .Net has done a lot to prevent using exceptions for flow control. For example they add tryparse for parsing strings into various datatypes in 2.0.

  • Misha (unregistered)
    Comment held for moderation.
  • FDF (unregistered) in reply to DOA
    DOA:
    To get a bit biblical... He who has never used exceptions in this manner, cast the first stone
    Here, catch my stone.
  • Mcoder (cs) in reply to DOA
    DOA:
    To get a bit biblical... He who has never used exceptions in this manner, cast the first stone

    captcha: Noone gives a rat's ass

    I would be first, but it seems people have aready got there. The real WTF it that his hash maps can have duplicated keys. The fact that it trows an exceptions is a plus. And, no, I don't know .net enough to know if it is true, or if the program is just wrong.

    The 'contains(value)' solution isn't good either, now your code uses O(n^2) operations, when the original uses just O(n).

  • Jim (unregistered)

    There's no Set object in .Net? In Java we just do:

    Set unique = new HashSet();
    unique.addAll(Arrays.asList(strObj));

    Done.

  • snoofle (unregistered) in reply to Jim
    Jim:
    There's no Set object in .Net? In Java we just do:
    Set unique = new HashSet();
    unique.addAll(Arrays.asList(strObj));
    Done.
    Hey, your LOC count is waaaay too low for this to be solid code - beef it up a little!
  • zip (cs) in reply to Mcoder
    Mcoder:
    The real WTF it that his hash maps can have duplicated keys. The 'contains(value)' solution isn't good either, now your code uses O(n^2) operations, when the original uses just O(n).

    The real WTF is that you have no idea what you're talking about.

    The exception he's using is caused by duplicate keys.

    Hashtables have O(1) lookup.

  • Twon (unregistered) in reply to Mcoder

    I believe .Net Hashtables store keys in some sensible (read: tree) data structure rather than just a list; I don't think .ContainsKey does an O(n) pass through the whole list of keys any time. Assuming some kind of balanced binary tree, you're looking at O(n lg n) instead, which is not so bad.

    Also, check your math on the original solution -- the recursion adds a heaping helping of extra, wasted computation if there are any duplicated values.

  • NateP (unregistered) in reply to akatherder
    akatherder:
    So now it's bad form to rely on an exception in your standard code path? Picky picky.

    Exception handling is expensive.. unwinding the stack and all..

  • Jones McFaggot (unregistered) in reply to Twon

    FRIST POST!

    THE REAL WTF IS

    CAPTCHA: dubya - Mandate of Heaven

  • guy (unregistered) in reply to Twon

    Umm... no.

  • Symbiatch (unregistered)

    Umm, I don't know if it's some kind of a requirement in this case to use hashtables (probably not since it's an example), but I wouldn't if I just needed to find unique values. I'd just use:

    List<string> Unique; foreach(string s in strObj) if(! Unique.ContainsKey(s)) Unique.Add(s);

    But maybe I'm just stupid. (And in .NET 1.1 I'd just use ArrayList)

  • guy (unregistered) in reply to Twon
    Twon:
    I believe .Net Hashtables store keys in some sensible (read: tree) data structure rather than just a list; I don't think .ContainsKey does an O(n) pass through the whole list of keys any time. Assuming some kind of balanced binary tree, you're looking at O(n lg n) instead, which is not so bad.

    Also, check your math on the original solution -- the recursion adds a heaping helping of extra, wasted computation if there are any duplicated values.

    What part of the name "Hashtable" suggests that there is a tree involved?

  • Nomen Nescio (unregistered)

    even taking the exception-in-ordinary-code-path thing as given, isn't there a bug in the way the exception is handled? if the last item in the array is a dupe, won't the exception "handler" risk advancing the loop counter too far?

    or i could be worng, seeing as i still haven't managed my morning cup of coffee yet. gotta get on that problem now.

  • Yartz (unregistered) in reply to Lastchance
    Lastchance:
    Ah, the old "use exception handling for non-exceptional logic" trick. That's the third time this week!

    Yes, I just got my "Get Smart" DVD set.

    Well, it's not such a big deal in many languages. Just because .Net exceptions are SO EXPENSIVE, does not mean catching exceptions in mainstream logic is so horrid.

    In Python, for instance, the try to insert then catch if it's there is a somewhat agreed on pattern (with the motto "it's easier to be forgiven than to be granted").

    Anyway, the code snippet was a little braindead anyway. And in .Net you should not merrily throw exceptions like this. No huge WTF, just poor code.

  • Justin (unregistered)

    I think I'll take the original programmer over some of these commenters.

  • Hellfire (unregistered) in reply to Misha

    The real WTF is that the Article got a rating of 4/5...

    CAPTCHA: pling-pling - spaboing - pling

  • Will Perdikakis (unregistered) in reply to zip
    zip:
    Mcoder:
    The real WTF it that his hash maps can have duplicated keys. The 'contains(value)' solution isn't good either, now your code uses O(n^2) operations, when the original uses just O(n).
    Hashtables have O(1) lookup.
    Beat me to it!

    Mcoder,

    The point of a hashtable is to store data for quick finds later. Based on the hash value, you can jump directly to the "bucket" where the value is stored, you do NOT iterate through. However, you then have to iterate that bucket (Unless it is doubly hashed) until you find the value. This is usually not a problem since that bucket is usually significantly smaller than the total number of elements.

  • dave (unregistered)

    No. no no no. exceptions do not belong as part of the main flow of a program. just dont do it kids.

  • Marko (unregistered) in reply to Twon
    Twon:
    I believe .Net Hashtables store keys in some sensible (read: tree) data structure rather than just a list; I don't think .ContainsKey does an O(n) pass through the whole list of keys any time. Assuming some kind of balanced binary tree, you're looking at O(n lg n) instead, which is not so bad.

    Also, check your math on the original solution -- the recursion adds a heaping helping of extra, wasted computation if there are any duplicated values.

    I believe .NET hashtable stores keys in a hashtable. I suggest you do a little research on a hash tables subject.

  • newt0311 (unregistered) in reply to Yartz
    Yartz:
    Lastchance:
    Ah, the old "use exception handling for non-exceptional logic" trick. That's the third time this week!

    Yes, I just got my "Get Smart" DVD set.

    Well, it's not such a big deal in many languages. Just because .Net exceptions are SO EXPENSIVE, does not mean catching exceptions in mainstream logic is so horrid.

    In Python, for instance, the try to insert then catch if it's there is a somewhat agreed on pattern (with the motto "it's easier to be forgiven than to be granted").

    Anyway, the code snippet was a little braindead anyway. And in .Net you should not merrily throw exceptions like this. No huge WTF, just poor code.

    It should also be noted in python that the get method is significantly faster especially if something does not exist because, exception handling is expensive.
  • Twon (cs) in reply to Marko

    Completely right. I need more coffee this morning...

  • Faxmachinen (unregistered) in reply to Nomen Nescio
    Nomen Nescio:
    even taking the exception-in-ordinary-code-path thing as given, isn't there a bug in the way the exception is handled? if the last item in the array is a dupe, won't the exception "handler" risk advancing the loop counter too far?
    Would be amusing if that caused a segfault exception. It's not a problem though, the while loop is just skipped when index >= strObj.Length. But it does give you one Console.ReadLine() too many.
  • RON (unregistered)

    The REAL WTF is these comments.

    Seriously WTF.

  • Xr (unregistered) in reply to guy
    guy:
    Twon:
    I believe .Net Hashtables store keys in some sensible (read: tree) data structure rather than just a list; I don't think .ContainsKey does an O(n) pass through the whole list of keys any time. Assuming some kind of balanced binary tree, you're looking at O(n lg n) instead, which is not so bad.

    Also, check your math on the original solution -- the recursion adds a heaping helping of extra, wasted computation if there are any duplicated values.

    What part of the name "Hashtable" suggests that there is a tree involved?

    And what would be the point in a hash table without O(1) operations ? BTW, balanced trees are O(log n), not O(n log n)

  • Cloaked User (cs) in reply to Yartz
    Yartz:
    Well, it's not such a big deal in many languages. Just because .Net exceptions are SO EXPENSIVE, does not mean catching exceptions in mainstream logic is so horrid.

    Yes, that's why they're called exceptions - because they're normal occurrences, and not exceptional at all...

    Anyone using exception handling as part of the normal control flow of their code on one of my projects is going to have to have an exceptionally good reason, or they're going to be rewriting it.

  • RobertB (cs) in reply to guy
    guy:
    This person was probably translating VB6 code. I believe in VB6 collections did not have .contains, and using On Error Resume Next and checking the error number was the only way to check if the collection had a given key.

    .Net has done a lot to prevent using exceptions for flow control. For example they add tryparse for parsing strings into various datatypes in 2.0.

    It also looks like this code from the VB6 project I work with.

    Public SomeFunction () As String
    On Error GoTo EmptyArray
    j = UBound(iSomething)
    On Error GoTo 0
    If j >= 0 Then
    ...
    End If
    Exit Function
    
    EmptyArray:
        'An array has not been initialized.
        If Err = 9 Then
            j = -1
            Resume Next
        Else
            SomeFunction = ""
            Exit Function
        End If
    
    End Function
    
    

    Since this is apparently the only* way to identify an empty array, I can't run the application with "break on all errors" set, at least not until I get into my own code.

    • In my code, I set a second variable to indicate whether the array has been initialized. I still wonder, though, if I'm missing something more elegant. And don't bother with "switch to .NET" or "use a real language". That horse is dead, stop beating it.
  • SuperousOxide (cs)

    There's no Set in .Net? And adding to a HashTable with a previously used key throws an exception?

    Anyway, the part I like is calling the function again every time you throw the exception, rather than just skipping that item and continuing the loop.

  • igitur (unregistered) in reply to guy

    I agree. Definitely translated VB6 code.

    I hate that thing. I'm having to work on a project that was "upgraded" from VB6 to VB.NET, then thrown into a VB.NET -> C# converter. Furthermore, the "developer" decided that having different Subs / Functions wasn't necessary because they were called all after each other in a predetermined fixed order.

    The result... one looooong function of about 1600+ lines of C# code, vaguely resembling VB6 flow.

  • slinkp (unregistered) in reply to SuperousOxide
    Comment held for moderation.
  • Josh (unregistered) in reply to Twon
    Twon:
    I believe .Net Hashtables store keys in some sensible (read: tree) data structure rather than just a list; I don't think .ContainsKey does an O(n) pass through the whole list of keys any time. Assuming some kind of balanced binary tree, you're looking at O(n lg n) instead, which is not so bad.

    Also, check your math on the original solution -- the recursion adds a heaping helping of extra, wasted computation if there are any duplicated values.

    I love how people conjecture about what they don't know just to make a point. That should be the real WTF. Just bullshiting here but now let me have a point.

  • Pesho (unregistered)

    My gut reaction was pretty much the one proposed by the second smartass, but what's more important, the REAL WTF is, of course C#. Why? Because you can't call a xxx on Dictionary to do the job, like, say d.xxx( key, ... ). No, you have to do d[key] = ..., and it just plain sucks bigtime that exported functionality REQUIRES special syntax (i.e. you can't do it with a plain old function call.)

    (Of course this does not wholly excuse the poor sod :) He could have discarded the exception within the iteration, as the next smartass suggested.)

  • ST ST (unregistered)

    uhm...

    ^aCollection asSet.

    Smalltalk wins

  • Brian (unregistered) in reply to Mcoder
    1. hasmaps don't allow duplicate keys for classes that have properly implemented HashCode() (in java and .Net).

    2. the cleaner option is NOT O(n^2) - the very point of a cleanly implemented hash based collection strategy is to speed lookups. If you've not implemented a hashtable/map you won't know this bit of practical information.

    Conclusion - your response is as WTF as the original code....

  • RON (unregistered)

    Here is the best way to do it in .NET 2.0

    No need to mess around with the inefficient hashtable class.

    	static class Unique
    	{
    		static IEnumerable<T> FindDuplicates<T>( IEnumerable<T> collection )
    		{
    			Dictionary<T, object> unique = new Dictionary<T, object>();
    
    			foreach( T t in collection )
    				unique[t] = null;
    
    			return unique.Keys;
    		}
    	}
    
  • -j (unregistered)

    F/OSS using the patent minefield that is .NET? Seems unduly rash!

  • joe.edwards (cs) in reply to DOA
    DOA:
    To get a bit biblical... He who has never used exceptions in this manner, cast the first stone

    captcha: Noone gives a rat's ass

    /me casts the first stone.

  • Eduardo Habkost (unregistered) in reply to DOA
    DOA:
    To get a bit biblical... He who has never used exceptions in this manner, cast the first stone
    first_stone = (Stone)stones[0];
  • Leadhyena (unregistered)

    This is nothing. Back in the dot-com days I worked for a stock trading firm that was writing their own trading system in Java 1.2. If only I remembered any of the code nowadays, I'd send it in, because it totally was WTF quality. One of their 'hallmarks' was a signaling system that was based entirely on exception handling. They would throw exceptions as signals that would hit the parent caller that would then act as an operator to another child process. The best part of the system was that none of it had comments. Our CTO at the time would brag about the sheer complexity of the system, and how something that was so complicated couldn't possibly be so wrong.

    throw new CAPTCHAException("Smile! Your code is crap.");

  • J (unregistered) in reply to Pesho
    Pesho:
    the REAL WTF is, of course C#. Why? Because you can't call a xxx on Dictionary to do the job, like, say d.xxx( key, ... ). No, you have to do d[key] = ..., and it just plain sucks bigtime that exported functionality REQUIRES special syntax (i.e. you can't do it with a plain old function call.)

    Oh, what a tragedy!! Poor C# coders are forced to use the same syntax that is used in every other collection in the language on their hash table. Typing a square bracket puts a person through so much suffering. All other aspects of a language which commits such a pernicious evil should be ignored, as they'll surely be overshadowed by a syntax variation.

  • Akerbos (unregistered) in reply to guy
    guy:
    What part of the name "Hashtable" suggests that there is a tree involved?
    What part of the name "Vector" suggests that there is an array involved?

    All of you that just use library funcions, be remembered that a library function also has to work for its effects. Personally, I would only call a function/solution "bad" if it ends in undefined behaviour or it is significantly slower than another one. Optimization while compiling is your friend. In dubio pro reo.

    Anyway, funny idea of the original writer. Wonder if he feels dirty today.

  • Aaron (unregistered) in reply to Pesho
    Pesho:
    My gut reaction was pretty much the one proposed by the second smartass, but what's more important, the REAL WTF is, of course C#. Why? Because you can't call a xxx on Dictionary to do the job, like, say d.xxx( key, ... ). No, you have to do d[key] = ..., and it just plain sucks bigtime that exported functionality REQUIRES special syntax (i.e. you can't do it with a plain old function call.)
    Hashtable.Add Hashtable.ContainsKey Hashtable.ContainsValue Hashtable.Remove Hashtable.get_Item Hashtable.set_Item

    The last two are hidden by C# but that's what you'll see in the CLI. Properties and default accessors are syntactic sugar that make our lives as developers easier, not harder. Not everybody loves verbosity for the sake of verbosity. Regardless, it's still fully compatible with languages that don't support that uh, "special syntax".

    Mind you, only .NET 1.x programmers still use the Hashtable. The .NET 2.0 framework introduced Dictionary<TKey, TValue> which also has the TryGetValue method, a very convenient one that I use extensively.

    Really, people need to read more than 3 lines from the first Google search result before they open their mouths.

    For any .NET programmers who are really anxious to get sets, or bags, or non-unique dictionaries, etc., just get the free PowerCollections library. Or wait for 3.0 which will have most of these built in for LINQ (and you can run SQL-like queries on them).

  • Aaron (unregistered) in reply to Akerbos
    Akerbos:
    guy:
    What part of the name "Hashtable" suggests that there is a tree involved?
    What part of the name "Vector" suggests that there is an array involved?
    Aside from the two words being almost synonymous in the English language, the very first sentence in the class documentation is, "The Vector class implements a growable array of objects." Or, in J#, "Represents a dynamic array of elements."

    Hashtable does not mention anything about a tree, nor should it, since it's implemented using a hash table.

  • Artemus Harper (unregistered) in reply to J

    If we assume we were using just the letters A-Z, then a simple solution that "inlines" the hashset would be:

    bool[26] values = new bool[26]; //all values are false.

    foreach(string s in array) { int index = s[0]-'A'; if(values[index]) { values[index] = true; Console.WritLine(s); } }

    For anything else, just remember that java and c# every object has the hashcode/Hashcode method. But since hashcodes can collide, we need buckets. If any string value was allowed, then yes, the worst time for this is:O(n^2)

  • Michael (unregistered) in reply to guy
    guy:
    What part of the name "Hashtable" suggests that there is a tree involved?
    Um, the "Hashtable" part? Seriously, how do you think a hashtable is implemented? Here's a hint: it's not a list.

Leave a comment on “Unique Ways to Play Catch”

Log In or post as a guest

Replying to comment #:

« Return to Article