-1

I have two files, database file and a new file which I have to compare. The values which are not present in the database file but are in the new file are processed further.

I am using hash tables for both database and new file in which key/value pairs are in the format -

("ABC,12","12,ABC")

The issue is that I am unable to perform hashtable comparison properly. For example, if my database file's hashtable has the following values-

("ABC,12","12,ABC")
("XYZ,Sample","Sample,XYZ")

and the new file has values

("ABC,12","12,ABC")
("ABC,20","20,ABC")
("XYZ,SAMPLE","SAMPLE,XYZ")

By using the following code

if (!_database.ContainsKey(KeyValueinNewFile)

I am getting the following output

("ABC,20","20,ABC")
("XYZ,SAMPLE","SAMPLE,XYZ")

It should only be

 ("ABC,20","20,ABC")

I have also used

Hashtable ht = System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable();

and

Hashtable ht = new Hashtable(StringComparer.InvariantCultureIgnoreCase);

but it is not working. Please suggest me something in which I do not have to make major changes in the application.

  • what is the value of `KeyValueinNewFile` ? – Eamonn McEvoy Apr 12 '20 at 08:42
  • KeyValueinNewFile has string values . For example, "XYZ,SAMPLE" – Seeker1201 Apr 12 '20 at 08:43
  • In your example you show `("ABC,12","12,ABC")`, is this 1 or 2 entries. k: "ABC" v: "12" and k: "12" v: "ABC" ? or k: "ABC,12" v: "12,ABC" ? Also, I'm not clear what case sensitivity has to do with it, all the examples are uppercase? – Eamonn McEvoy Apr 12 '20 at 08:46
  • 1
    Why hashtable? IMO a `Dictionary` (or possible just a `HashSet`) should be fine here; you can pass a `StringComparer` (such as `OrdinalInoreCase`) to the constructor of that (those) – Marc Gravell Apr 12 '20 at 08:46
  • @EamonnMcEvoy Key is "XYZ,SAMPLE" and value is "SAMPLE,XYZ" . Case insensitivity is required because database has ("XYZ,Sample","Sample,XYZ") . The Sample is in lowercase but in the new file SAMPLE is in upper case. Ideally, it should be ignored in comparision – Seeker1201 Apr 12 '20 at 08:50
  • The way you configure the case insensitivity looks correct. Have you stepped through with the debugger to see exactly which value of `KeyValueinNewFile` is giving you the unexpected result? Also, as @MarcGravell suggested, a Dictionary would be a better choice here. – Eamonn McEvoy Apr 12 '20 at 08:57
  • yes I have debugged with the upper written scenario only, it is giving me the ("ABC,20","20,ABC") ("XYZ,SAMPLE","SAMPLE,XYZ") . Ideally, it should have given me result as ("ABC,20","20,ABC") – Seeker1201 Apr 12 '20 at 09:01
  • I tried something ( I know I should have not ) - I wrote if(string.Equals((!_database.ContainsKey(KeyValueinNewFile),StringComparison.InvariantCultureIgnoreCase) but it then skipped every value. – Seeker1201 Apr 12 '20 at 09:02
  • Is there anyway I can simply typecast value and get the comparison done. it would require me minimum code changes – Seeker1201 Apr 12 '20 at 09:03
  • Can you post the full code? – Eamonn McEvoy Apr 12 '20 at 10:35
  • no need now. I used dictionary and it worked ! :) Actually, I wanted to try using hashtable only that's why trying hard to find a way out ! – Seeker1201 Apr 12 '20 at 10:51

1 Answers1

0

The easiest approach will be to just perform full outer join on old and new collections and find the difference, the same way you do in any SQL-like syntax (see the answer from @sehe):

LINQ - Full Outer Join

Example:

//see, you can pass comparer inside, it also uses hashtables for performance inside.
var fjoin = _database.FullOuterJoin(newFile, x=> x, x=> x, (x,y,key)=> new {oldObj = x, newObj = y}, cmp: StringComparer.InvariantCultureIgnoreCase);

var toFurtherProcess = fjoin.Where(x=> x.oldObj == null);

Not compiled, just by memory. The benefit of this approach is that you can fully sync two collections: find whats missing in first one, what is already present by key and what is missing in second one (means need to be deleted). You got full Create, Update, Delete sync.

eocron
  • 6,885
  • 1
  • 21
  • 50
  • Thank you for your response but it would be helpful if you could suggest how can I compare using hashtables only as they are only required for the scenario. – Seeker1201 Apr 12 '20 at 08:53
  • HashSets accept custom made IEqualityComparer, to compare values in table. Just add your case-insensetive comparer - *var hs = new HashSet(StringComparer.InvariantCultureIgnoreCase);* I would however note that FULL JOIN is common practise for sync tasks, it also more clever. This extension one of the most used when you work with some kind of 1-1 linked data. – eocron Apr 12 '20 at 08:57