Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

Using LINQ, how can I compare two Dictionary for search same text contain in value, not consider key?

What I have tried:

C#
Dictionary<int, string> dictionary1 = 
                       new Dictionary<int, string>();
					   
					   dictionary1.Add(7, "SELECT");
          dictionary1.Add(2, "UPDATE");
          dictionary1.Add(6, "CREATE");
		   dictionary1.Add(4, "UNION");
		    dictionary1.Add(5, "JOIN");
			
			Dictionary<string, string> dictionary2 = 
                       new Dictionary<string, string>();
					   
					   dictionary2.Add(7, "SELECT");
          dictionary2.Add("Id", null);
          dictionary2.Add("FName", "create");
		   dictionary2.Add("LName", "Denny");
		    dictionary2.Add("DateofJoining", null);
			dictionary2.Add("Date", "2023 - 08 - 01T00: 00:00");
			dictionary2.Add("CreatedBy", "ICC0000389");


After compare the two Dictionary get a bool value if same text is matching.

C#
bool isMatch = dictionary2.Concat(dictionary1.Where(kvp => !dictionary2.ContainsValue(kvp.Value))); // here I am getting error.


Thanks!
Posted
Updated 10-Aug-23 5:02am
Comments
PIEBALDconsult 10-Aug-23 9:38am    
I hope you're not planning on using string concatenation to form SQL statements from the data in the JSON file like that.
I recommend you rethink what you are planning to do as it is unlikely to be a very good solution.
Step back and think about the high-level process you are trying to develop.
PIEBALDconsult 15-Aug-23 11:05am    
I must assume that you are concerned about the values being SQL injection attacks. You are right to be concerned, but the correct solution is to use a parameterized SQL statement.
If, on the other hand, you wish to flag suspicious input for review, rather than blindly insert it, then maybe this technique has merit.
However, you should still be aware that some good data values may contain what appear to be SQL keywords. For instance: "OUTER BANKS", "DROP SHIPMENT", "ROUND TABLE". It may still be worthwhile to insert all the data (with a parameterized SQL statement) and then perform a search for SQL injection attempts for review.

Basically, do not attempt to detect SQL injection then adjust for it in order to use string concatenation to create the INSERT statement -- it's not even very efficient.
Does your database system not support parameters?

You need to fix your key issue in the second Dictionary. You have defined it as:
C#
Dictionary<string, string>

If you want to mix int and string, then change to:
C#
Dictionary<object, string>

Now, you're looking for the intersection of the 2 dictionaries, ie: the exclusive matches. You also want to match the values, and not the keys. So...
C#
Dictionary<int, string> dictionary1 = 
    new Dictionary<int, string>();
		   
dictionary1.Add(7, "SELECT");
dictionary1.Add(2, "UPDATE");
dictionary1.Add(6, "CREATE");
dictionary1.Add(4, "UNION");
dictionary1.Add(5, "JOIN");

Dictionary<object, string> dictionary2 = 
    new Dictionary<object, string>();
		   
dictionary2.Add(7, "SELECT");
dictionary2.Add("Id", null);
dictionary2.Add("FName", "create");
dictionary2.Add("LName", "Denny");
dictionary2.Add("DateofJoining", null);
dictionary2.Add("Date", "2023 - 08 - 01T00: 00:00");
dictionary2.Add("CreatedBy", "ICC0000389");

var list1 = dictionary1.Select(x => x.Value);
var list2 = dictionary2.Select(x => x.Value);
var matches = list1.Intersect(list2);
foreach (string match in matches)
{
    Console.WriteLine(match);
}

Which outputs:
SELECT
 
Share this answer
 
Comments
Richard Deeming 10-Aug-23 6:28am    
You could replace dictionary.Select(x => x.Value) with dictionary.Values. :)

IDictionary<TKey,TValue>.Values Property (System.Collections.Generic) | Microsoft Learn[^]
Graeme_Grant 10-Aug-23 6:31am    
That too. I was just being very verbose.
I got a bad feeling about this...


Here's how to do it using HashSets directly rather than mucking about with Linq, but it's not a very good technique:

C#
System.Collections.Generic.Dictionary<int,string> dictionary1 =
  new System.Collections.Generic.Dictionary<int,string>
  (
  )
  {
    { 7 , "SELECT" }
  ,
    { 2 , "UPDATE" }
  ,
    { 6 , "CREATE" }
  ,
    { 4 , "UNION"  }
  ,
    { 5 , "JOIN"   }
  } ;

System.Collections.Generic.Dictionary<string,string> dictionary2 =
  new System.Collections.Generic.Dictionary<string, string>
  (
  )
  {
    { "Id"            , null                       }
  ,
    { "FName"         , "create"                   }
  ,
    { "LName"         , "Denny"                    }
  ,
    { "DateofJoining" , null                       }
  ,
    { "Date"          , "2023 - 08 - 01T00: 00:00" }
  ,
    { "CreatedBy"     , "ICC0000389"               }
  } ;

System.Collections.Generic.HashSet<string> intersection =
  new System.Collections.Generic.HashSet<string>
  ( dictionary1.Values , System.StringComparer.InvariantCultureIgnoreCase ) ;

intersection.IntersectWith ( new System.Collections.Generic.HashSet<string>
  ( dictionary2.Values , System.StringComparer.InvariantCultureIgnoreCase ) ) ;

bool isMatch = intersection.Count > 0 ;
 
Share this answer
 
v2
A problem with this solution and what you have asked for is that the JSON file you are reading may contain millions of objects and this technique has certain inefficiencies which will not scale well.
You should not keep building a HashSet from the static list of SQL keywords only to use it once and then throw it away (perhaps millions of times per file) -- which is what Linq will do in the background.
Furthermore, if all you want to know is whether or not any one value is in the set, then a full Intersection of the two sets isn't necessary (a Contains should be enough).

Here's another way to test a set of string values against a fixed set of strings which should be more efficient than intersecting sets:

C#
namespace CP
{
  public static partial class DicValCompare
  {
    private enum SQLstring
    {
      SELECT = 7
    ,
      UPDATE = 2
    ,
      CREATE = 6 
    ,
      UNION  = 4
    ,
      JOIN   = 5
    }

    public static int
    Main
    (
    )
    {
      int result = 0 ;

      System.Collections.Generic.Dictionary<string,string> dictionary2 = 
        new System.Collections.Generic.Dictionary<string,string>
        (
        )
        {
          { "Id"            , null                       }
        ,
          { "FName"         , "create"                   }
        ,
          { "LName"         , "Denny"                    }
        ,
          { "DateofJoining" , null                       }
        ,
          { "Date"          , "2023 - 08 - 01T00: 00:00" }
        ,
          { "CreatedBy"     , "ICC0000389"               }
        } ;

      bool isMatch = false ;
      SQLstring sql ;

      foreach ( string val in dictionary2.Values )
      {
        if 
        ( 
          ( val != null ) 
        && 
          ( isMatch |= System.Enum.TryParse ( val , true , out sql ) ) 
        )
        {
          break ; // val is an SQLstring
        }
      }

      return ( result ) ;
    }
  }
}
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900