Compare two dictionary entries.

I have a dictionary of messages. (Timestamped primary key)
Within each message type there is a dictionary with string values and string keys.
i need to loop through the dictionary of messages to see if any of the messages are duplicates messages but with different timestamps.

for each m in mMessages if m.MessageText = "ThisTypeOfMessage" then for each m1 in mMessages if m.MessageText = "ThisTypeOfMessage" then if m <> m1 then // not reference to the same object. if deepcompare(m, m1) then system.DebugLog("Stop") end if end if end if next end if next

This code to me looks real stupid but ‘should’ work.
so
a) Is there a way to do away with this bubble sort like loop so that I only check from where I am to the end of the dictionary rather than starting the inner loop at the beginning every time? i.e. can i use indices?

b) how would deepcompaire two dictionary entries (from different dictionaries) to each other, knowing that both key and values are strings?

why not (instead of a dictionary) use an in-memory SQLite database

SELECT message,count(*) as count FROM myMessageTable GROUP by MESSAGE having count(*)>1

return all the duplicate messages in one statement

OR
create another dictionary, keyed by the MESSAGE

for each m in messages
if otherDict.hasKey(m) then 
/// its a dup
else
otherDict.value(m)=x // what x is doesn't matter
end if

Wow! What a great idea. I wish I had thought of that before.
I think that is going to be the approach I take right after this issue is resolved. (I never thought I’d hear myself say that)
I mean I get where you are going but too much code at the moment is working with dictionaries.
unless I’m missing something obvious…

[quote=339293:@Dave S]why not (instead of a dictionary) use an in-memory SQLite database

SELECT message,count(*) as count FROM myMessageTable GROUP by MESSAGE having count(*)>1

return all the duplicate messages in one statement

OR
create another dictionary, keyed by the MESSAGE

for each m in messages if otherDict.hasKey(m) then /// its a dup else otherDict.value(m)=x // what x is doesn't matter end if [/quote]

d1
k=“abc”
v=“123”

d2
k=“abc”
v=“234”

not the same.

Not understanding what you are trying to say…
That SQL statement WILL return only ONE occurance of every message that appears more than once in the table

[quote=339300:@Dave S]if otherDict.hasKey(m) then
/// its a dup
else[/quote]

I’m saying that simply comparing the keys isn’t sufficient the keys and values need to be identical for the tables to be identical.
but then maybe I’ve misread your sql.

I proposed TWO different methods

Method #1 - requires an In-Memory SQLite table containing your messages

SELECT message,count(*) as count FROM myMessageTable GROUP by MESSAGE having count(*)>1

Method #2 - can use the current structures… just add a 2nd dictionary

for each m in messages
if otherDict.hasKey(m) then 
/// its a dup
else
otherDict.value(m)=x // what x is doesn't matter
end if

your post says

Therefore I took these “specifications” to indicate there were TWO fields involved, MESSAGE and TIMESTAMP, and the requirement was to find instances of MESSAGE that occurred more than one time…

Method #1 returns the UNIQUE “message”, the # of times it occurred, and only if it occurred more than once

Method #2 pours the messages into a 2nd dictionary… if during the “FOR EACH” loop, the message had already been entered, then it won’t be entered into that dictionary again, at the end of the “FOR EACH” loop, the “otherDict” has a list of all the unique messages that occurred more than once… but NOT how many times it did occur.
NOTE : Method #2 requires AN ADDITIONAL DICTIONARY (otherDict)… this is NOT the dictionary you have now…

The two methods are NOT related… they are two different approachs to the same problem.

I still appreciate the input Dave.
Clarity is so hard…

1 dictionary that has many elements (the base class of a message). Time stamp being the key.
each element has a dictionary of key value pairs that may or may not be alike.
are those two dictionary entries identical?
Values are always strings.

I want to get rid of the double for loop and use indices. i.e. avoid comparing elements to the left of the current pointer again.

I am not sure what part of creating the 2nd dictionary and keying it by the MESSAGE is eluding you

lets go here… since you have not posted your entire code snippet… I will make some assumptions

  • Assumption #1 you have an existing dictionary that the has TIMESTAMP and MESSAGE… for sake of this topic, I will call the BRIAN_DICTIONARY
dim DAVE_DICTIONARY as NEW DICTIONARY
dim message as string
FOR each key as string in BRIAN_DICTIONARY // key is your TIMESTAMP
message=BRIAN_DICTIONARY.value(key) // this is the message.. :)
  if DAVE_DICTIONARY.hasKey(message)=false then DAVE_DICTIONARY.VALUE(message)=1
NEXT
//
// DAVE_DICTIONARY now has a list of all the messages that occurred more than one time

Here is what i have.

What is missing is how the inner for loop can be optimized such that it starts off at the key after key rather than starting at the beginning of the key list.

for each m in mMessages if m.MessageText = "ThisMessageName" then for each m1 in mMessages // Really why must I start at the beginning I want to start at m + 1 if m1.MessageText = "ThisMessageName" then if m <> m1 then // not reference to the same object. if deepCompare(m.Data, m1.Data) then // operator overload? // Flag both messages as having a duplicate (or more) end if end if end if next end if next

So maybe like this…

  for i=0 to mMessages.Ubound-1
    m = mMessages(i)
    if m.MessageText = "ThisMessageName" then
      for j=i+1 to mMessages.Ubound
        m1 = mMessages(j)
        if m1.MessageText = "ThisMessageName" then
          if deepCompare(m.Data, m1.Data) then
                // Flag both messages as having a duplicate (or more)
          end if
        end if
      next
    end if 
  next [/code]


This is the deep compare dictionary.

[code]Function deepCompare(d1 as Dictionary, d2 as Dictionary) As Boolean
  dim key, keys(-1) as Variant
  dim value as string
  
  if d1 <> nil and d2 <> nil then
    if (d1 <> d2) then  // I don't compare myself to myself. (redundant)
      // better have the same number of entries
      if (d1.Count > 0) and (d1.Count = d2.Count) then
        
        keys = d1.Keys
        for each key in keys
          if d2.HasKey(key) then
            if d1.Value(key) <> d2.Value(key) then
              return false  // value not the same.
            end if
          else
            return false // doesn't have the same keys
          end if
        next
        return true  // every thing is the same.
      else
        return false  // Dictionaries aren't the same size
      end if
      // Not reached
    else
      return true  // If its a reference to the same object then I bet they are the same.
    end if
  end if
  return false  // one or the other or both are nil.  throw something?
  
End Function

Ok… good luck