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?
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…
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.
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
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