Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by BilboStabbins · Feb 02, 2014 at 07:37 AM · newline

Dictionary only matching last word in list

Hi,

I'm trying to write a simple dictionary program that checks whether a word entered by the user is present. I've created a GUI button that does the checking and outputs the result.

The program was working fine (matching ALL the words entered that were in the dictionary/text file) and then suddenly couldn't match any of the words apart from the last one in the list.

I can't for the life of me see what the problem is as all my debugging confirms that the words are being parsed from the dictionary.txt file into the dictionary correctly.

I'm using wordArray = MytextAsset.text.Split('\n'); // Have also tried ("\n"[0]) to separate the words in the text file and myDictionary = wordArray.ToDictionary(s => s, s => true); to convert the array into a Dictionary. The text file looks like this;

 one
 two
 three

So here, only 'three' can me matched/found from the dictionary and 'one' and 'two' can't be.

My check for the word is as follows:

 return myDictionary.ContainsKey(word);

and only returns true for 'three' - the last word in the list. I have even set the word string explicitly directly before the check, as follows; word = "one"; to eliminate any errors in passing it to the variable.

I thought that it could be a problem with the newline character in the text file for the first 2 words. However, I've tried creating the file several times, with the same result. The only difference I can see is that the word 'three' wouldn't have a newline character next to it (as I don't have to hit Enter to type another word on the next line), but 'one' and 'two' would.

Any help would be great.


Complete code below:

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 
 public class WordListDictionary : MonoBehaviour
 {
     private string wordToCheck = " ";                                      // Word to check against words in dictionary
 
     private Dictionary<string, bool> myDictionary = new Dictionary<string, bool>();                  // Dictionary used to store words
 
     private string[] wordArray = new string[4];                                     // Array used to temporarily store the words in the text file
 
     public GameObject[] CharBoxArray = new GameObject[3];           // Array holding the boxes with child with TextMesh
 
     public GameObject[] SlotsArray = new GameObject[3];             // Array holding the slots with child with TextMesh
 
     private TextAsset MytextAsset;                                  // Used to store the data in the dictionary.txt file                                 
 
     private string resultString = " ";                               // Used to display string showing whether made word is found in dictionary or not
 
     void Awake()
     {
         // Read in the dictionary.txt file which is in the Resources folder in the project
         // and store it in a TextAsset variable/object
         MytextAsset = Resources.Load("dictionary", typeof(TextAsset)) as TextAsset;
 
         // Add the words to a string array and use the \n (newline) character to separate the word
         // So when a newline is reached, it means its a new word
         wordArray = MytextAsset.text.Split('\n'); // Have also tried ("\n"[0])
 
         // For debugging
         print("wordArray[0] = " + wordArray[0]);
         print("wordArray[1] = " + wordArray[1]);
         print("wordArray[2] = " + wordArray[2]);
 
         // Convert the array containing the words to a Dictionary, passing in the correct KeyValuePair types (string, bool)
         myDictionary = wordArray.ToDictionary(s => s, s => true);
 
         // Simultaneously convert the Dictionary to a List and then run a ForEach loop to print out the values of the Keys 
         // Note this is not the usual foreach loop which uses an enumerator. ForEach is part of the List<T> class and uses a for-loop
         myDictionary.ToList().ForEach(x => Debug.Log(x.Key + ", " + x.Value));
     }
 
     bool checkWord(string word)
     {
         print("myDictionary.ContainsKey(word) = " + myDictionary.ContainsKey(word));
 
         return myDictionary.ContainsKey(word);
     }
 
 
     void Update()
     {
         wordToCheck = "one";
         checkWord(wordToCheck);
         print("wordToCheck = " + wordToCheck);    
     }
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image KellyThomas · Feb 02, 2014 at 09:54 AM 0
Share

Have you double checked that wordArray has the right content?

avatar image BilboStabbins · Feb 02, 2014 at 01:50 PM 0
Share

Yes, placing;

 print("wordArray[0] = " + wordArray[0]);
 print("wordArray[1] = " + wordArray[1]);
 print("wordArray[2] = " + wordArray[2]);

beneath the ..split('\n') line outputs the following;

 wordArray[0] = one
 wordArray[1] = two
 wordArray[2] = three

and also to check the dictionary conversion, placing the line:

 myDictionary.ToList().ForEach(x => Debug.Log(x.$$anonymous$$ey + ", " + x.Value));

beneath the line;

 `myDictionary = wordArray.ToDictionary(s => s, s => true);` 

outputs

 one,True
 two, True
 three, True

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by KellyThomas · Feb 02, 2014 at 03:09 PM

I've not used ToDictionary() personally but it looks like your code:

 myDictionary = wordArray.ToDictionary(s => s, s => true); 

might be resolving to this overload:

 ToDictionary<TSource, TKey>(Func<TSource, TKey>, IEqualityComparer<TKey>)

If this is occurring then passing true as the second parameter would means that all values would be treated as equal. If that is happening then each new string that may be overwriting the previous, possibly explaining the behaviour you observe.

Are you planning on using the values stored in the Dictionary?

If you are only interested in the absence/presence of a key you might find success with this overload:

  Dictonary<string, string> myDictionary = wordArray.ToDictionary<string, string>(s => s);


Or better still you could use a `HashSet`:

 HashSet<string> dictHash = new HashSet<string>(wordArray);

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image BilboStabbins · Feb 03, 2014 at 01:40 AM 0
Share

Thanks for your suggestions, $$anonymous$$elly - they are much appreciated.

Currently I only need to know if the word is present in the dictionary. I tried replacing the line with yours:

 `Dictonary<string, string> myDictionary = wordArray.ToDictionary<string, string>(s => s)`;

but it unfortunately gives the same result of 'false' for the first 2 words and 'true' for the 3rd. I used the same method to test for a word:

 myDictionary.Contains$$anonymous$$ey(word);

I've heard a lot of about HashSets and their speed so will look into them if I can't get around this.

I've included the complete script at the bottom of my answer if it will help figure things out.

Thanks

avatar image KellyThomas · Feb 03, 2014 at 10:50 AM 0
Share

O$$anonymous$$ I ran your code and think I have identified the problem.

You are splitting on "`\n`" the line forward character but it is likely that the line endings in your textfile are CR+LF or "`\r\n`".

This would result in all but the last word having the (invisible) "`\r`" character included at the end of it's string.

Try using this code to split:

 using System;
 //...
 wordArray = $$anonymous$$ytextAsset.text.Split(new char[]{'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
avatar image BilboStabbins · Feb 03, 2014 at 05:49 PM 0
Share

You nailed it - that was the problem!

Working great now - $$anonymous$$any Thanks :)

While we're on the subject, I notice that while writing the dictionary.txt file in Notepad+ (with 'End of line' set to visible) that on some occasions a CRLF is added and at other times just an LF. Would you know why this might be the case?

Thanks in advance

avatar image KellyThomas · Feb 04, 2014 at 12:09 AM 0
Share

Good stuff I'm glad it's working.

I don't know why Notepad++ would be creating mixed line endings, but you can convert / configure with Edit - EOL Conversion and select from Windows / $$anonymous$$ac / Unix.

The code above was intended to literally demonstrate the problem, I think this would be a good approach to use (it also cleans blank lines and trailing spaces):

 $$anonymous$$ytextAsset.text.Split(new char[] { '\r', '\n' })
                 .Select(s => s.Trim())
                 .Where(s => s.Length > 0)
                 .ToArray();
               //.ToDictionary(s => s, s => true);
avatar image BilboStabbins · Feb 05, 2014 at 03:57 AM 0
Share

That great - I'll have a fiddle with Notepad+ and see what can be done there.

I also implemented this using a Hashset. However (and correct me if I'm wrong), most sources say they're only really useful if their advanced functionality is needed (Overlaps, SymmetricExceptWith, etc.). As is most cases Dictionaries are supposed to perform better/faster.

Thanks for the thorough answer.

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

19 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to I write native newline Characters (when using the systemCopyBuffer)? 1 Answer

Line break in xml 1 Answer

Making newline ( \n ) in inspector 11 Answers

New line \n character is not working in GUILayout.label 1 Answer

Line break in button text 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges