-
Adding a dictionary instead of a list
Ok, am trying to replace bad words with Good words from a RichTextBox from a dictionary file. The program as it is, can only do it from a preloaded list. How do you do this in Visual Basic? Press F8 to run the program to see what it can do.
This is a grammar checker. Check my file from this link.
Dictionary wordlist
Code:
Public Class Form1
Friend WithEvents RichTextBox1 As New RichTextBox With {.Dock = DockStyle.Fill}
Friend WithEvents ReplaceMenu As New ContextMenuStrip
Private replacements As New Dictionary(Of String, IEnumerable(Of TextReplacement))
Private nextCheckIndex As Integer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Controls.Add(RichTextBox1)
replacements.Add("a bad advice", {New TextReplacement("a bad suggestion", "Replace advice with suggestion."),
New TextReplacement("some bad advice", "Replace a with some.")})
replacements.Add("irregardless", {New TextReplacement("regardless", "Irregardless is not a word."),
New TextReplacement("in spite", "Reword the phrase.")})
RichTextBox1.Text = "You provided a bad advice, irregardless of your intention. You provided a bad advice, irregardless of your intention. "
End Sub
Private Sub RichTextBox1_KeyUp(sender As Object, e As KeyEventArgs) Handles RichTextBox1.KeyUp
If e.KeyCode = Keys.F8 Then
nextCheckIndex = 0
CheckForReplacementText()
End If
End Sub
Private Sub CheckForReplacementText()
If nextCheckIndex = replacements.Count Then
MessageBox.Show("Check complete.")
Else
Dim checkWord = replacements.Keys.ElementAt(nextCheckIndex)
Dim foundIndex = RichTextBox1.Find(checkWord, 0, RichTextBox1.TextLength, RichTextBoxFinds.WholeWord)
If foundIndex > -1 Then
ReplaceMenu.Items.Clear()
For Each replacement In replacements(checkWord)
With ReplaceMenu.Items.Add(replacement.Text, Nothing, Sub(sndr As Object, ea As EventArgs)
RichTextBox1.SelectedText = replacement.Text
CheckForReplacementText()
End Sub)
.AutoToolTip = True
.ToolTipText = replacement.Reason
End With
Next
ReplaceMenu.Show(RichTextBox1, RichTextBox1.GetPositionFromCharIndex(RichTextBox1.SelectionStart + RichTextBox1.SelectionLength))
Else
nextCheckIndex += 1
CheckForReplacementText()
End If
End If
End Sub
End Class
Public Class TextReplacement
Public Property Text As String
Public Property Reason As String
Public Sub New(replacementText As String, replacementReason As String)
Text = replacementText
Reason = replacementReason
End Sub
End Class
-
Re: Adding a dictionary instead of a list
If you're going to post code then please use code tags. Not surprisingly, quote tags are for quotes, not code. As you can see, the lack of formatting makes the code less than simple to read.
-
Re: Adding a dictionary instead of a list
Please now help me I have done it.
-
Re: Adding a dictionary instead of a list
-
Re: Adding a dictionary instead of a list
I'm a little confused. You already have a Dictionary in there. What exactly do you want that you don't already have? Do you actually want to know how to use the Dictionary, despite the fact that your question actually asks how to add it? Are you asking how to populate the Dictionary from some external source? Please be clear.
-
Re: Adding a dictionary instead of a list
yes, am trying to populate it from a file. I have a big file, but it cannot fit in the code program of my program. So, I only want to use my file as a dictionary instead of list that you put in a program. I will really appreciate this help that your offering. It will be good to know how you do this sought of thing, and again for Christmas.
-
Re: Adding a dictionary instead of a list
Your first post doesn't mention anywhere that your issue is reading data from a file. You really need to be CLEAR when posting. We know nothing about what you're doing other than what you tell us so you have to tell us everything that is relevant. Don't expect us to read between the lines; write an extra line.
It's still not 100% clear to me what you're asking for either. Are you saying that you want to know how to read data from the file into a generic Dictionary object or that you want to read directly from the file as required instead of using a generic Dictionary object?
-
Re: Adding a dictionary instead of a list
Ok, I have edited the question now you can understand it.
-
Re: Adding a dictionary instead of a list
You generally read a text file using a StreamReader or perhaps a TextFieldParser. What does the format of the file look like?
-
Re: Adding a dictionary instead of a list
It looks like this:
avoided|averted
That is how it is delimited
-
Re: Adding a dictionary instead of a list
Then you should probably use a TextFieldParser. The MSDN documentation for the class provides a code example of its use.
-
Re: Adding a dictionary instead of a list
I know how it is used and I have a sample. The tricky part is with (Of String, IEnumerable(Of TextReplacement))
I could not find any documentation anywhere.
-
Re: Adding a dictionary instead of a list
If I use (Of String, String)
it gives me an error on my list, but when I change the below sections to ToString, it works, but only shows one character at a time.
With ReplaceMenu.Items.Add(replacement.Text
RichTextBox1.SelectedText = replacement.Text
-
Re: Adding a dictionary instead of a list
Quote:
Originally Posted by
nqioweryuadfge
The tricky part is with (Of String, IEnumerable(Of TextReplacement))
Why has it taken you until post #12 to say that, even after talking about posting clearly earlier?
Firstly, do you actually need an IEnumerable(Of TextReplacement)? Are you going to store multiple values against each key? If not then there's no need for an IEnumerable at all. Also, what is a TextReplacement? Are you intending to use them or do you just want to store simple text? If the latter then just use String instead.
You need to first be clear about what you're going to use and then actually use it. If you put Strings into the Dictionary then you are going get Strings out so you have to use them as Strings, which will not work if the code expects TextReplacement objects. If you need TextReplacement objects then that's what you have to create in the first place.
As for an IEnumerable, the most common implementation would be either an array or a generic List. So, if you want to use a Dictionary(Of String, IEnumerable(Of TextReplacement) then you would most likely add a TextReplacement array or a List(Of TextReplacement) against each String key.
-
Re: Adding a dictionary instead of a list
Ok, how can I use this code to work in my program. Here is the link to my dictionary file
Code:
Dim replacements As New Dictionary(Of String, Tuple(Of String, String))
replacements.Add("bad word", New Tuple(Of String, String)("good word", "reason this is better"))
Dim replacement = replacements("bad word")
Dim newWord = replacement.Item1
Dim reason = replacement.Item2
-
Re: Adding a dictionary instead of a list
I have tried to do a research and found nothing that can help me to solve this issue. But if there is a way you can demonstrate with your code, that would be helpful.
-
Re: Adding a dictionary instead of a list
Please help, I have done all my research and found no solutions.
-
Re: Adding a dictionary instead of a list
Assuming that each line of the file is two string separated by a pipe, you can populate a Dictionary like this:
vb.net Code:
Dim replacements As New Dictionary(Of String, String)
Using reader As New StreamReader("file path here")
Do Until reader.EndOfStream
Dim parts = reader.ReadLine().Split("|"c)
replacements.Add(parts(0), parts(1))
Loop
End Using
You could then use the replacements like so:
vb.net Code:
For Each key In replacements.Keys
sourceText = sourceText.Replace(key, replacements(key))
Next
-
Re: Adding a dictionary instead of a list
It is saying sourceText is not declared, but how will it fit here:
Code:
For Each replacement In replacements(checkWord)
With ReplaceMenu.Items.Add(replacement.ToString, Nothing, Sub(sndr As Object, ea As EventArgs)
RichTextBox1.SelectedText = replacement.ToString
CheckForReplacementText()
End Sub)
-
Re: Adding a dictionary instead of a list
Quote:
Originally Posted by
nqioweryuadfge
It is saying sourceText is not declared...
Of course it does, if you didn't declare it. It seems like some people don't understand the concept of an example. I've shown you how to the Dictionary in that example. Noe you apply that same concept to your own situation.
-
Re: Adding a dictionary instead of a list
That was not the issue. The problem was to apply the code on ContextMenu.
-
Re: Adding a dictionary instead of a list
If I use this code as it is, it will not allow the Context to work! Also, it is abit complecated for me to adjust it on the part I have just highlighted because I have not reached that level in programming.
-
Re: Adding a dictionary instead of a list
And again you haven't actually explained what you want but have just expected me to work it from code that doesn't actually do it.
-
Re: Adding a dictionary instead of a list
I just wanted to use a file instead of a preloaded list. You told me you understood that earlier! I only want your code to work on the ContextMenu that I sent to you earlier. It's where am stack.
-
Re: Adding a dictionary instead of a list
My knowledge is very limited to execute the kind of thing your asking me to do.
-
Re: Adding a dictionary instead of a list
I know its hard to feed me that in-tell, but this verse says: 1 Thessalonians5: 11 So encourage each other to build each other up.
You may send me a private message.
-
Re: Adding a dictionary instead of a list
I would suggest that quoting scripture to JMc is unlikely to get you a positive outcome.
You have code here:-
Code:
For Each replacement In replacements(checkWord)
With ReplaceMenu.Items.Add(replacement.ToString, Nothing, Sub(sndr As Object, ea As EventArgs)
...that will populate a context menu from a dictionary called replacement. It was working when you populated the dictionary from code. JM has shown you how to populate a dictionary from a file. Your code to populate the context menu should remain completely unaffected and should just work.
So where are you actually struggling now? Where does your code fail?
edit>Ah, I think I might see it. You are populating your dictionary in the form load event and I think you are assuming that any given keyword (checkWord) might have several values in the dictionary. That's why you originally had a Dictionary of string, ienumerable - so that each check word could have several possible replacements. Is that correct.
-
Re: Adding a dictionary instead of a list
Yes, I see you get it now! That is what I was hoping for. The (checkWord) was very puzzling as to how, it can be replaced.
Also, I was wondering how this code would be implemented in the Context:
Code:
For Each key In replacements.Keys
sourceText = sourceText.Replace(key, replacements(key))
Next
-
Re: Adding a dictionary instead of a list
This part is saying an item with the same key has already been added:
Code:
replacements.Add(parts(0), parts(1))
-
Re: Adding a dictionary instead of a list
How can I resolve the problem
-
Re: Adding a dictionary instead of a list
Ok, I will try to find the content online..
-
Re: Adding a dictionary instead of a list
I don't have visual studio to hand so I'm typing straight off the cuff and am liable to make small mistakes. Hopefully I can point you in the right direction though.
Quote:
I was wondering how this code would be implemented in the Context:
First you'd get the iEnumerable of replacement words from your dictionary:-
Code:
Dim replacementWords = iEnumerable(of String)
replacementWords = replacements(checkWord)
Then you would iterate through the enumerable adding each word to your context menu:-
Code:
For Each word as String In replacementWords
ReplaceMenu.Items.Add(word)
Next
The code to populate your dictionary will also need to change slightly. JM gave you the basic code in post 18 but we're going to need to change the bit where it adds to the dictionary. Instead of this (which will always add an element to a dictionary):-
Code:
replacements.Add(parts(0), parts(1))
...you want to check whether your checkWord (which will be parts(0)) is already in the dictionary. If it is, retrieve the enumerable and add your new replacement word to it. If it isn't you create a new enumerable and add that to your dictionary:-
Code:
if replacements.contains(parts(0))
replacements(parts(0)).Add(parts(1))
else
Dim newWordList as iEnumerable(of String)
newWordList.Add(parts(1))
replacements.Add(parts(0), newWordList)
end if
I think that's correct but be wary of my syntax. Without visual studio in front of me it's very likely I've made a mistake or two which you will have to correct. Regardless, it should help demonstrate the principle.
-
Re: Adding a dictionary instead of a list
1
down vote
Your question has already been answered, but IIRC you can replace lines like:
if d.has_key(scope_item):
with:
if scope_item in d:
That is, d references d.keys() in that construction. Sometimes defaultdict isn't the best option (for example, if you want to execute multiple lines of code after the else associated with the above if), and I find the in syntax easier to read.
Thanks , :)
-
Re: Adding a dictionary instead of a list
I think that will work, let me try it.
-
Re: Adding a dictionary instead of a list
First am getting this errors here:
Code:
Dim replacementWords = iEnumerable(Of String)()
Code:
Enumerable is a type, and cannot be used as an expression
Secondly, am getting this error here:
Code:
String cannot be converted to Systems.Collections.Generic.KeyValuePair(Of String, Systems.Collections.Generic.IEnumerable(Of WindowsApplication1.TextReplacement)
from here:
Code:
replacements.Add(parts(0), parts(1))
If replacements.Contains(parts(0)) Then
replacements(0).Add(parts(1))
Else
Dim newWordList As IEnumerable(Of String)
newWordList.Add(parts(1))
replacements.Add(parts(0), newWordList)
End If
-
Re: Adding a dictionary instead of a list
I did say I'd probably make a few syntax errors
Quote:
First am getting this errors here:
Change the = to an As
Quote:
String cannot be converted to Systems.Collections.Generic.KeyValuePair(Of String, Systems.Collections.Generic.IEnumerable(Of WindowsApplication1.TextReplacement)
I believe Baileykos's answer in post 33 should fix that. Instead of using replacements.contains use replacements.has_key.
Also, note that you should have removed "replacements.Add(parts(0), parts(1))". Your post makes it look like you've left it in there.
-
Re: Adding a dictionary instead of a list
OK, I was researching on the problems. That is why I was caught up in the mix up. But thanks
-
Re: Adding a dictionary instead of a list
I get you now, did you mean for here:
Code:
if d.has_key(scope_item):
with:
if scope_item in d:
To be implemented here:
Code:
If replacements.Contains(parts(0)) Then
replacements(0).Add(parts(1))
-
Re: Adding a dictionary instead of a list
I think that should correctly read either:-
Code:
if replacements.has_key(parts(0))
replacements(parts(0)).Add(parts(1))
or
Code:
if parts(0) in replacements.keys()
replacements(parts(0)).Add(parts(1))
depending on the syntax you prefer
-
Re: Adding a dictionary instead of a list
There is an error on Add
Code:
Add is not a member of Systems.Collections.Generic.IEnumerable
Now, I have done some research, and considered that maybe this might resolve the issue, but how would it work on a file delimited file?
Code:
https://msdn.microsoft.com/en-us/library/z883w3dc%28v=vs.110%29.aspx
-
Re: Adding a dictionary instead of a list
I am getting this error:
Code:
has_key is not a member of Systems.Collections.Generic.Dictionary(Of String, is not a member of Systems.Collections.Generic.IEnumerable
From here:
Code:
if replacements.has_key(parts(0))
replacements(parts(0)).Add(parts(1))
Also,
Code:
Add is not a member of Systems.Collections.Generic.IEnumerable
-
Re: Adding a dictionary instead of a list
Quote:
Add is not a member of Systems.Collections.Generic.IEnumerable
Damn, that's true. You need a concrete type rather than an interface. I would suggest a List.
Change this:-
Code:
Dim replacementWords as List(of String)
to this
Code:
Dim replacementWords as List(of String)
and this:-
Code:
Dim newWordList As IEnumerable(Of String)
to this
Code:
Dim newWordList As List(Of String)
Quote:
has_key is not a member of Systems.Collections.Generic.Dictionary
Had a quick google, it ContainsKey not has_key
-
Re: Adding a dictionary instead of a list
And here:
Code:
replacements As New Dictionary(Of String, IEnumerable(Of TextReplacement))
-
Re: Adding a dictionary instead of a list
Yes, that one too. There's an argument for declaring objects as interfaces rather than concrete types but that's probably just a distraction for you at this stage. Just change iEnumerable to List everywhere it occurs.
-
Re: Adding a dictionary instead of a list
I was forced to change to the following as a result of the changes made above:
Code:
If replacements.ContainsKey(parts(0)) Then
replacements(parts(0)).Add(parts(1))
Else
Dim newWordList As List(Of String)
newWordList.Add(parts(1))
replacements.Add(parts(0), newWordList)
But these parts are saying:
parts(1)
Code:
Value of type 'String' cannot be converted to 'WindowsApplication1.TextReplacement
newWordList
Code:
Value of type 'System.Collections.Generic.List(Of String)' cannot be converted to 'System.Collections.Generic.List(Of WindowsApplication1.TextReplacement)
-
Re: Adding a dictionary instead of a list
Change this:-
Private replacements As New Dictionary(Of String, IEnumerable(Of TextReplacement))
to this:-
Private replacements As New Dictionary(Of String, IEnumerable(Of String))
-
Re: Adding a dictionary instead of a list
It worked but only showed one suggestion instead of many suggestions.
-
Re: Adding a dictionary instead of a list
Could it be, because Add is not a member of Enumerable, and Equals is the cause of this limitation?
Code:
If replacements.ContainsKey(parts(0)) Then
replacements(parts(0)).Equals(parts(1))
-
Re: Adding a dictionary instead of a list
E.g. If we are replacing the word bad. Here are the suggestions we should use:
Code:
bad|counterproductive (means negative)
bad|inappropriate
bad|unsuitable
-
Re: Adding a dictionary instead of a list
You certainly shouldn't be using Equals. Where did that come from?
I made a mistake in my previous post, I should have said:-
Private replacements As New Dictionary(Of String, List(Of String))
You should not reference iEnumerable anywhere in your code. Change it to List everywhere it occurs. Once you've done that the Add will be allowed.
-
Re: Adding a dictionary instead of a list
Very good it is working. I don't know how to thank you. It is working fine. Do you anything to do with ignore functions?
-
Re: Adding a dictionary instead of a list
I will consider this as a paid service.
-
Re: Adding a dictionary instead of a list
Wait, that logic is wrong and I'm not even sure where it came from. It's not the logic I posted back in post 32. Go back to post 32, read the code I posted, understand it, and only then should you use it. And don't forget, I have no ide in front of me. I will make mistakes so if you try and use my code without understanding it you will not spot those mistakes and it will fail.
Let's recap:-
Your replacements dictionary is a dictionary of lists. It is keyed by the word you want to replace (checkWord) and each element is a list of words you would use to replace that checkWord. Correct? So your dictionary should be declared like this:-
Code:
Dim replacements as new Dictionary(of string, list(of string))
See how that's a dictionary keyed by a string (this will be your checkWord) containing lists of strings (the valid replacements for each checkWord)
Now you are going to iterate through your file getting pairs of words - the first (part(0)) is the checkWord and the second (part(1)) is a valid replacement. JM showed you how to do this:-
Code:
Using reader As New StreamReader("file path here")
Do Until reader.EndOfStream
Dim parts = reader.ReadLine().Split("|"c)
'Here we will update the dictionary using part(0) and part(1) - see blow
Loop
End Using
Now, when populating replacements, each pair of words in your file is going to be a checkWord and a possible replacement. You might have already created an element in the dictionary for that checkWord or you might not so you need to check:-
Code:
If replacements.ContainsKey(part(0))
Do you see how that's going to return true if the checkWord (Part(0)) has already been placed in the dictionary?
If the checkWord is already in your dictionary it means you have already found at least one replacement word for this checkWord in your file. In that case you do not add the checkword again. If you try it will fail and you will get the duplicate key already exists error. Instead you should add the new replacement word to the list of words you already hold for that checkWord:-
Code:
replacements(part(0)).add(part(1))
Do you see how replacements(part(0)) is going to return you the appropriate list of replacements for the checkWord you're dealing with? And do you see how .Add(part(1)) will add the newly found replacement word for that list?
On the other hand, if the if statement above returns false it means the checkWord (part(0)) isn't already in your dictionary. It means this is the first replacement we've found for that checkWord. In that case we need to create a new list of replacement words for that checkWord containing the newly found replacement word. Then we will put that new list into the dictionary using the newly found checkWord (Part(0)) as a key:-
Code:
Dim newWordList as new List(Of String)
newWordList.Add(part(1))
replacements.Add(part(0))
Do you understand the logic behind the process we're carrying out? Not just the syntax but the steps we're taking and why we're taking them. Unless you understand the logic you will never get through this so concentrate on that understanding first.
edit>
Quote:
Very good it is working.
Our posts crossed over so I didn't see this. That's great to hear but I'd still urge you to read this post carefully and make sure you've understood the logic correctly. If you haven't it's possible that it might appear to work but still be doing something you don't expect.
-
Re: Adding a dictionary instead of a list
Yes, I understand this part:
Code:
if replacements.contains(parts(0))
replacements(parts(0)).Add(parts(1))
else
Dim newWordList as iEnumerable(of String)
newWordList.Add(parts(1))
replacements.Add(parts(0), newWordList)
end if
-
Re: Adding a dictionary instead of a list
Cool, then I think you're probably there:)
-
Re: Adding a dictionary instead of a list
The only problem I see in the code is something like this:
If you replaced the word gave in a sentence like this:
Code:
You gave a bad advice, irregardless of your intention. You provided a bad advice, irregardless of your intention
With these suggestions:
Code:
gave|produced
gave|provided
gave|supplied
gave|yielded
It will have a problem because of an error coming from here:
Code:
Dim foundIndex = RichTextBox1.Find(checkWord, 0, RichTextBox1.TextLength, RichTextBoxFinds.WholeWord)
After you suggest the word supplied to replace gave, it is Automatically replacing supplied with yielded. Try that wordlist you will see.
-
Re: Adding a dictionary instead of a list
Do you anything to do with ignore functions? I will consider this as a paid service.
-
Re: Adding a dictionary instead of a list
Try the wordlist and you will notice the error it is bringing. It is replacing supplied with yielded without Authorization.
Code:
gave|produced
gave|provided
gave|supplied
gave|yielded
-
Re: Adding a dictionary instead of a list
I'm sorry but I didn't understand that. Are you saying it's picking the wrong replacement word from your list? If so we'd need to see the code you use to do that actual replacement. It's probably in the context menu's click event.
-
Re: Adding a dictionary instead of a list
Yes, I have found a code that can resolve the problem:
Code:
Private Sub ReplaceMenu_ItemClicked(sender As Object, e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles ReplaceMenu.ItemClicked
Dim checkWord = replacements.Keys.ElementAt(nextCheckIndex)
ReplaceMenu.Items.Clear()
For Each replacement In replacements(checkWord)
replacement = e.ClickedItem.ToString()
RichTextBox1.SelectedText = replacement
Next
End Sub