C
C#3mo ago
workani

Populating a Dictionary from a CSV File with Words Separated by Semicolons

Hi, I want to create a small console app for learning new vocabulary, and I need to populate a dictionary (source language: target language) from a CSV file that contains vocabulary in this format: english;german\n. How could I populate a dictionary?
104 Replies
Pobiega
Pobiega3mo ago
When you say dictionary, do you mean an actual Dictionary<string, string>? with what language being key and what being value, in that case? The classic "ask a question and immediately go offline so now followup questions can be asked" tactic.
workani
workaniOP3mo ago
I want to use English word as key and German as value
Pobiega
Pobiega3mo ago
Okay. Do you want to use this as a learning experience or just have the answer?
workani
workaniOP3mo ago
I want to learn
Pobiega
Pobiega3mo ago
Okay great. So, what would be a logical place to start?
workani
workaniOP3mo ago
Use a for loop with Split method? To iterate thru each line and populate arrays
Pobiega
Pobiega3mo ago
something along those lines, sure but we can use LINQ and functional coding to do this
workani
workaniOP3mo ago
Sounds interesting
Pobiega
Pobiega3mo ago
the data from our file can be either a raw string or a string[], depending on how you read it
workani
workaniOP3mo ago
Okay, I want to treat it as a string
Salman
Salman3mo ago
Normally you read the data line by line if not using CSV reader or something..
Pobiega
Pobiega3mo ago
okay, so we read the file into a single string.
var data = File.ReadAllText(...);
var data = File.ReadAllText(...);
next, we do need to split it by lines, since each line contains one key-value pair how would you do that?
workani
workaniOP3mo ago
Pobiega, Is it good idea to use a single dictionary for displaying English words and checking user input with German words? Split it by \n char and put it in array?
Pobiega
Pobiega3mo ago
I mean, it could cause problems with case sensitivty and multi-word words, but other than that, should be fine?
workani
workaniOP3mo ago
Would it be hard to deal with both problems?
Pobiega
Pobiega3mo ago
okay, lets go with that
var result = File.ReadAllText(data)
.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
var result = File.ReadAllText(data)
.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
I added some options to split to clean up data. not strictly needed, but can help if the csv files contains a trailing blank line, or whitespace
workani
workaniOP3mo ago
Now the hardest part, populating two different arrays
Pobiega
Pobiega3mo ago
well, if we wanna do linq, we dont do that 🙂 We're gonna use something called .Select this lets us transform our sequence (currently an array of strings) into a new sequence
workani
workaniOP3mo ago
Which condition will we put in select method?
Pobiega
Pobiega3mo ago
no condition. Select doesnt take a condition, it takes a Func<TSource,TResult>
var result = File.ReadAllText(data)
.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(x => x)
var result = File.ReadAllText(data)
.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(x => x)
we can start with this a sample line might look like.. thank you;danke what would be a good transformation to apply here?
workani
workaniOP3mo ago
Wow Separate string by semicolon?
Pobiega
Pobiega3mo ago
yes!
var result = File.ReadAllText(data)
.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(x => x.Split(';'))
var result = File.ReadAllText(data)
.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(x => x.Split(';'))
workani
workaniOP3mo ago
Will it give us a list back?
Pobiega
Pobiega3mo ago
okay, result is now a sequence of string[]s no, not unless we call .ToList to make it a list but we dont want to do that we can still work with it as a sequence (IEnumerable)
workani
workaniOP3mo ago
So it’s a sequence of all words?
Pobiega
Pobiega3mo ago
well, its a sequence of string arrays, where the first item in each array is the english word, and the second is the german word I dont think we can do any more meaningful transformations at this point, so we should just "finish" the sequence by collecting it into its final shape: a dictionary
workani
workaniOP3mo ago
I think now we need to put first object to sequence to english words array and second to German array How could we do that?
Pobiega
Pobiega3mo ago
Well, LINQ has a lovely .ToDictionary method I suggest we use that 😄
workani
workaniOP3mo ago
Nice
Pobiega
Pobiega3mo ago
it has a few different overloads, but the one we probably want is...
workani
workaniOP3mo ago
Side question: how does sequence look like?
Pobiega
Pobiega3mo ago
ToDictionary(keySelector, valueSelector) wdym?
workani
workaniOP3mo ago
And what is it?(in simple language)
Pobiega
Pobiega3mo ago
the type of a "sequence" in C# is IEnumerable<T>
Pobiega
Pobiega3mo ago
No description
Pobiega
Pobiega3mo ago
you can see here from my Rider window
workani
workaniOP3mo ago
Okay Could we apply it to our linq query?
Pobiega
Pobiega3mo ago
we certainly can What do you suggest we use for keySelector and valueSelector?
workani
workaniOP3mo ago
But is it good practice to put so much of methods to one line of code?
Pobiega
Pobiega3mo ago
they should be Func<TSource, TResult>s sure, why not? we are breaking it up so its readable and lovely
workani
workaniOP3mo ago
Pobiega, I need to go to important meeting now. Could I hit you up in DM after I’ll comeback?
Pobiega
Pobiega3mo ago
I'd argue this is a lot more readable than the nested loops that would do this without linq no, but you can ping me here
workani
workaniOP3mo ago
Okay, thanks @Pobiega, I’m back
MODiX
MODiX3mo ago
Pobiega
What do you suggest we use for keySelector and valueSelector?
React with ❌ to remove this embed.
workani
workaniOP3mo ago
What should I pass to ToDictionary method?
Pobiega
Pobiega3mo ago
Two funcs One that selects the key, one that selects the value
workani
workaniOP3mo ago
Could I use Split method two times? @Pobiega
Angius
Angius3mo ago
You can .Select() to split each element first, then .ToDictionary() the results of that split
Pobiega
Pobiega3mo ago
we've already done that we're at
var result = File.ReadAllText(data)
.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(x => x.Split(';'))
var result = File.ReadAllText(data)
.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(x => x.Split(';'))
the only thing left is the ToDictionary call with the two selectors so tell me @danilhieshka how would we get the key from our string[] thats currently in the sequence
workani
workaniOP3mo ago
I don’t know How could I do that?
Pobiega
Pobiega3mo ago
How would we get the first item from an array?
workani
workaniOP3mo ago
Should I use index 0 and 1?
Angius
Angius3mo ago
Yep
workani
workaniOP3mo ago
ToDictionary(0,1)?
Angius
Angius3mo ago
No .ToDictionary() takes two lambdas, as Poibiega already said The key selector, and the value selector
MODiX
MODiX3mo ago
Angius
REPL Result: Success
class Person
{
public int Id { get; set; }
public string Name { get; set; }
}

var people = new Person[] {
new Person { Id = 1, Name = "Bob" },
new Person { Id = 2, Name = "Anis" },
};

var dict = people.ToDictionary(person => person.Id, person => person.Name);

dict
class Person
{
public int Id { get; set; }
public string Name { get; set; }
}

var people = new Person[] {
new Person { Id = 1, Name = "Bob" },
new Person { Id = 2, Name = "Anis" },
};

var dict = people.ToDictionary(person => person.Id, person => person.Name);

dict
Result: Dictionary<int, string>
{
"1": "Bob",
"2": "Anis"
}
{
"1": "Bob",
"2": "Anis"
}
Compile: 466.067ms | Execution: 68.529ms | React with ❌ to remove this embed.
Angius
Angius3mo ago
For example
Pobiega
Pobiega3mo ago
the selectors are lambdas (anonymous functions) that take the current object in the sequence in, and produce whatever value you want as your key/value out so write a function in the format of x => x that takes a string[] in, and produces the key you want for that word combo then do the same for the value
workani
workaniOP3mo ago
ToDictionary(x => vocabulary.english, x => vocabulary.german)?
Pobiega
Pobiega3mo ago
well yes, but vocabulary doesnt exist reasonbly, you'd derive the values from x somehow and remember, x is the string[] that contains a single split word-combo ie, english and german
workani
workaniOP3mo ago
Simply x.0, x.1?
Angius
Angius3mo ago
Is that how you get items from an array?
Pobiega
Pobiega3mo ago
x is the array.
workani
workaniOP3mo ago
Ah, x[0], x[1]
Pobiega
Pobiega3mo ago
yes.
Angius
Angius3mo ago
Yep
workani
workaniOP3mo ago
Thank you guys!! Special thanks to Pobiega, your explanation was great
Pobiega
Pobiega3mo ago
and assuming basic C# knowledge, and understanding lambdas... I think this is so much more readable and understandable compared to doing it with loops LINQ is very very common in modern C#
workani
workaniOP3mo ago
I think you’re right What should I learn first, LINQ or basics of OOP?
Pobiega
Pobiega3mo ago
oop the basics of OOP are almost mandatory to understand C#, imho we write classes and methods all the time, so that just needs to be solid
workani
workaniOP3mo ago
Okay I kind understand how to create classes and use methods, but in very simple level
Pobiega
Pobiega3mo ago
thats fine you need to start somewhere 😄
workani
workaniOP3mo ago
I also wanted to ask, for the main part of the application, where the user would be asked to input vocabulary, should I use some kind of loop or another method?
Pobiega
Pobiega3mo ago
hm I thought you said it would be read from file? that makes more sense to me as a user, manually entering the vocabulary each time I want to practice seems silly 😄
workani
workaniOP3mo ago
Yep, but then user would be asked to translate vocabulary from English to German
Pobiega
Pobiega3mo ago
oh like, it would pick a random word and say "what is this in german?"
workani
workaniOP3mo ago
Yes
Pobiega
Pobiega3mo ago
yeah, that would be with a loop
workani
workaniOP3mo ago
And also, how to shuffle words? Great, thanks
Pobiega
Pobiega3mo ago
easiest way is probably to just make a copy of the dictionary key list, and sort it by random since you dont need any advanced type of shuffling
workani
workaniOP3mo ago
Could I use LINQ for sorting?
Pobiega
Pobiega3mo ago
yes
workani
workaniOP3mo ago
Which method will be appropriate in my case?
Pobiega
Pobiega3mo ago
.OrderBy
workani
workaniOP3mo ago
Like that ?
No description
Pobiega
Pobiega3mo ago
that seems expensive and also, frankly, not needed its probably simpler to just copy the keys, and generate a random index as needed when asked
Pobiega
Pobiega3mo ago
(no spoilers :D)
No description
workani
workaniOP3mo ago
That looks nice How could I implement it ?
Angius
Angius3mo ago
Random class
Pobiega
Pobiega3mo ago
Random.Shared.Next(max) generates a number between 0 and max-1 perfect for indexing a list/array of size max the code inside that loop is very simple, it checks for an early exit (pressing enter without typing a guess in my case), otherwise it just takes your guess, looks up the correct answer and then says if you got it right or not oh, and ofc it gets a random english word from the list of keys (english) as the very first thing
workani
workaniOP3mo ago
Should I use it inside .OrderBy method ?
Angius
Angius3mo ago
You can get the keys of the dictionary as a list Then get a random key
workani
workaniOP3mo ago
@Pobiega Hi. Could you explain me please in details, how does this code works and why did you used Select method? I want to understand this code deeply
Pobiega
Pobiega3mo ago
I already have
MODiX
MODiX3mo ago
Pobiega
this lets us transform our sequence (currently an array of strings) into a new sequence
React with ❌ to remove this embed.
workani
workaniOP3mo ago
@Pobiega Hi, shoudl I use a for loop to shuffle my vocab dictionary?
Angius
Angius3mo ago
Do you want to shuffle it, or just get a random item?
workani
workaniOP3mo ago
I want to shuffle it
Angius
Angius3mo ago
Fischer-Yates algorithm is usually the golden standard But there's also Random.GetItems() IIRC And Random.Shuffle() that does an in-place shuffling
Pobiega
Pobiega3mo ago
you dont shuffle it you just get a random index
workani
workaniOP3mo ago
Okay, but what if create a copy of a dictionary, shuffle it and then use it throught app;ication? Pobiega, I think you've already told me that I could use OrderBy method for that How could I do that exactly?
Pobiega
Pobiega3mo ago
Surely you can figure this one out on your own?
workani
workaniOP3mo ago
Sorry for asking too much
workani
workaniOP3mo ago
I've got it working
No description
Want results from more Discord servers?
Add your server