Adding and counting every word in a string to a linked list
-
21-12-2019 - |
Question
I'll start off by saying I haven't quite wrapped my head around OOP.
I need a routine that iterates through each word in a string, checks to see if it is in my linked list and either adds it as a node if it is not or increases the count of the existing node if it is in the list.
Here is what I have:
private void CountWords(string cleanString)
{
WordNode nextNode, prevNode;
WordNode addNode;
foreach (string stringWord in cleanString.Split(' '))
{
if (head == null)
{
// No items in list, add to the beginning
addNode = new WordNode(stringWord);
head = addNode;
}
else
{
if (String.Compare(stringWord, head.Word) < 0)
{
// If stringWord belongs at the beginning of the list, put it there
addNode = new WordNode(stringWord);
addNode.NextWord = head;
head = addNode;
}
else if (String.Compare(stringWord, head.Word) == 0)
{
// If stringWord is equal to head.Word, increase count
addNode.Count += 1;
}
else
{
prevNode = head;
nextNode = head.NextWord;
// If it doesn't belong at the beginning, cycle through the list until you find where it does belong
while ((nextNode != null) && (String.Compare(nextNode.Word, addNode.Word) < 0))
{
prevNode = nextNode;
nextNode = nextNode.NextWord;
}
if (nextNode == null)
{
prevNode.NextWord = addNode;
}
else
{
prevNode.NextWord = addNode;
addNode.NextWord = nextNode;
}
}
}
}
}
Before this, I was attempting the addNode = new WordNode(stringWord); at the beginning of each iteration through the "for each word in string" loop, but that would re define the class and reset count to 1. Now, currently, I can't increase the count, because addNode.Count += 1; is undefined. I was hoping I could check to see if stringWord was in the linked list, and if so, increment stringWord.count by one, but that throws an error.
Looking at this now, I'm thinking the addNode.Count += 1; belongs in the while loop a few lines below it...
Here is my WordNode class:
class WordNode
{
// constants
// variables
private string data; // this is our only data, so also key
private int count;
private WordNode next; // this is reference to next Node
// constructors
public WordNode(string newValue)
{
Word = newValue;
count = 1;
NextWord = null;
}
// methods
public string Word
{
get
{
return data;
}
set
{
data = value;
}
}
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
public WordNode NextWord
{
get
{
return next;
}
set
{
next = value;
}
}
}
Solution
Try this:
private void CountWords(string cleanString)
{
foreach (string stringWord in cleanString.Split(' '))
{
if (head == null)
{
head = new WordNode(stringWord);
}
else
{
var last = (WordNode)null;
var current = head;
do
{
if (current.Word == stringWord)
{
break;
}
last = current;
current = current.NextWord;
} while (current != null);
if (current != null)
{
current.Count++;
}
else
{
last.NextWord = new WordNode(stringWord);
}
}
}
}
And alternative is to use linq:
var query =
cleanString
.Split(' ')
.ToLookup(x => x)
.Select(x => new
{
Word = x.Key,
Count = x.Count(),
});
OTHER TIPS
It sounds like you are just trying to practice making a linked list so this might not be helpful, but a much simpler solution is to use Key/Value pair like a dictionary.
Dictionary<string, int> Words = new Dictionary<string, int>();
string wordsList = "a list of words for testing a list of words for testing";
foreach (string word in wordsList.Split(' '))
{
if (Words[word] == null)
Words[word] = 1;
else
Words[word] += 1;
}
System.Console.WriteLine("testing: {0}", Words["testing"]); //result- testing: 2
The result of indexing the Words dictionary by the string will return the number of words.
This looks like a job for a Dictionary or here
Dictionary<string,int> myDict = new Dictionary<string,int>();
foreach(string str in listOfWords)
{
myDict.add(str,0);
}
foreach(string x in cleanText.split(' '))
{
if(myDict.ContainsKey(x))
myDict[x]+=1;
}
After running through the foreach myDict will contain counts for each word in the "bag of words."
Edit
if(myDict == null)
myDict = new Dictionary<string,int>(); //assuming running tally at higher scope.
foreach(string x in cleanText.split(' '))
{
if(myDict.ContainsKey(x))
myDict[x]+=1;
else
myDict.add(x,1);
}