Need help with text files
There is a text file with numbers. First number means category and five others are points. I need to sum the points but have trouble doing it. Also there may be several categories with same number. If there are, they need to be showed as one same category and their points need to be summed.
182 Replies
What have you tried, and why didn't it work?
I was able to output first number of every line - categories
but dont know how to sum five following numbers
of every line
string filepath = @"C:\Users\Vartotojas\Desktop\task.txt";
var lines = new List<string>();
lines = File.ReadAllLines(filepath).ToList();
var category = new List<string>();
var points = new List<string>();
foreach (string line in lines)
{
category.Add(line.Split(' ')[0]);
}
foreach(string k in category)
{
Console.WriteLine(k);
}
heres what I got working so far
okay, the basics are there, but there are some problems here
You've correctly identified that you need to use
Split
to separate your string, but you are not storing the result, instead only getting the first numbers and ignoring everything else
Your points
is also not connected to a category, meaning you would lose that connection after parsing
So instead of List<string>
to store your data in, can you think of a more suitable type?honestly I cant
lol
array?
I thought list is the best
do you know the difference between an array and a list?
yeah
but still
you think I need to use array?
To be fair, neither is what I had in mind here
whoah
There are a few options - the goal is to sum each "category", so we could skip directly to that and just store the sum as we go
alternatively, we create one list per category, add all the points, then sum them at the end
which do you think sounds better/easier to understand?
this one
okay
buuut then every category would be in different list correct?
we need a way to associate a key (the category id) with a list of values (the "points")
correct
we need to keep them apart
would it later be possible to sort and compare them?
probably, but depends on what exactly you mena by "them" :p
the categories, or the points
if there are multiple categories with same numbers (like in my given file) I need to make them into one category
categories
1 15 20 22 5 9
and
1 9 6 8 7 12
so there should be 1 113 if im correct
sum all 10 numbers
right, so their total sum
for category 1
yeah
I was thinnking about this points.Add(line.Split(' ')[1]);
but idk
didnt work for me
well ofc not
points
isnt associated with any category
first, lets clean up a bit
thats a lot of noise. just var lines = File.ReadAllLines(filepath);
is perfectly fine
after that, we cant use two lists like that. as said, we need to associate the points with the category
luckily, there is a datatype that helps us do a Key-Value store: the Dictionary<TKey, TValue>
now, what would be your suggested types for TKey
and TValue
respectively?I dont think I've ever seen this Dictionary<TKey, TValue>
damn
my suggested types for them are int?
or wdym by type
yeah
int
would work
as the key
but if you use it as value, you would associate an int with another int... that works fine if we just store the sum
but you wanted to store the individual pointsthen what do you suggestðŸ˜
string/char?
how about
List<int>
?
each category (int
) stores the points ( List<int>
)so this would put every category number in one list?
no
a
Dictionary<int, List<int>>
would be a collection of key value pairsahh
where each pair has a single key (an int), and a value (a list of ints)
makes sense?
yeah
okay, so first we need to make one of those dictionaries
Dictionary<int, int> key = new Dictionary<int, int>();
like this?
almost
check what types you used
ints
ahh
wait xdf
yeah, and what did we say about
<int, int>
?Dictionary<int, List<int>> key = new Dictionary<int, List<int>>();
sure that works, I'd personally prefer
var categories = new Dictionary<int, List<int>>();
oh nah, you too smart xd
but now do I need this var category = new List<string>();?
nope
kk
we can safely throw that
ok, now to start parsing the lines
I dont need that split command too right?
category.Add(line.Split(' ')[0]);
not as such, but we will need to use
split
oh
right
okay, so
how do we parse our lines?
whats step 1
categories.Add(int.Parse(line)); something like this lmao
nawww
for one, it wont work, and two, its a bit too much
nah wait gimme a min
minute
sure
categories.Add(line, points); I give up
wellll
we need to do something with the string
like... turn it into a sequence of numbers, perhaps
with loop?
probably yeah
I don't think you'll be happy with me if I write a linq-oneliner for this 😄
but im tempted to try...
wait what
wdym by that
go ahead
tada...
I don't think this is very helpful thou 😛
it also has a bit of a bug
so dont worry about it
I think I saw something very similar when looking for help with my problem on google
its not what we want to do
aight
so
what do we need to do at "we are here"?
categories.Add(lines, ); is this even a good start or nah
no
rip
no add function?
what would you add?
categories and points
points doesnt exist
and categories is... the thing you are adding to
dude let me be real, I have no idea
it shouldnt even start with "categories"?
no
we need to do something to the text
the variable
line
contains the current string we are working on
that represents a single category and its items
do you remember .Split
?ofc
use it now?
yeah
but lets keep the result for now
ie, dont throw it away
we might also want to turn those strings into numbers at the same time
if you are comfortable with that
I am
ok, give me your best shot
int.Parse(line.Split(' ')[0]) something like this in a middle
close, but not quite
int.Parse
handles a single number
and we wanna parse all the numbers
so I present you...
this
I gotta go for ~10 min
try to understand this line of code while Ima wayhno way I could have had that rightðŸ˜
kkkk
You see there are three parts to that line ye?
Is it obvious what each part does?
I think I understand this
var numbers is an array now yeah?
oh wait, one question
line.Split(" ")
what exactly does it split?
every element divided by comma?
nah, not comma, space
exactly
it divides the string into many strings, each divided by a space
then, each item in that array (the array of split strings), is transformed with the
.Select
method
select applies another method to each thing in its sequence
in this case, it turns a string
into an int
and finally we .ToArray
the sequence so we get an arrayhow nice
now I need to turn first number of array into category?
or var numbers already dont contain category numbers
nah, it contains
It has all the numbers
So can you divide it into two variables, called key and points?
with another split?
Split is a method for strings
You now have an int array
var key = numbers.Take(0).ToArray();
Close
numbers[0]
is better
We just want the first, and we dont want it as an array
But how do we get the rest..?my original idea was to add five items to list
one by one with add()
or use getrange
we could do something like that, but I'd like to separate out the points first
is the best way, if you ask me
those two dots at the end are good or do I need to continue with that line?
haha, no they are good
it means "from 1, all the way to the end"
wtf I actually lack this much knowledge💀
well, Im not showing you the simplest most basic way to do things
im showing you modern syntax
points.Sum();
would this work?
int sum = points.Sum();
Console.WriteLine(sum);
Yeah it would, but its too early
Remember category 1?
yeah
ok Im lost a bit
var key
does it mean categories?
no
well
yes
it means the category id for this line
you could call it
categoryId
if you want
you still there?yeah xd
tryna do something
show me
right now nothing works but im trying to implement this
if (testArray.Length != testArray.Distinct().Count())
{
Console.WriteLine("Contains duplicates");
}
to check for same categories
uh
thats... not what it does
rip then
it checks for duplicate entries, not same category
ie
x 5 5
dont worry about duplicates yet
we'll handle thatthen what do I need to do rn?
I thought only about duplicates
show me what you got
string filepath = @"C:\Users\Vartotojas\Desktop\task.txt";
var lines = File.ReadAllLines(filepath);
var categories = new Dictionary<int, List<int>>();
foreach (string line in lines)
{
var numbers = line.Split(" ").Select(int.Parse).ToArray();
var key = numbers[0]; var points = numbers[1..]; int sum = points.Sum();
Console.WriteLine(key+" "+sum); }
var key = numbers[0]; var points = numbers[1..]; int sum = points.Sum();
Console.WriteLine(key+" "+sum); }
eight
right*
also, how do you make ur code darker in chat?
$codegif
thx
but notice how we are not interacting with
categories
at all inside the loop?
we are not doneyeah I was wondering about that xd
all we've done is process the individual line into its two parts, the category id and the points
the next part is getting the associated
List<int>
for the given category
now, there are two cases that are possible in this scenario
1. this is the first time we see this category
2. this is not the first time we see this categorybefore this, do I need to add key and points to categories?
no
thats what we are working on right now
we cant add now, because we dont know what to do
if we blindly try to add, what if the dictionary already contains the category (like 1)?
you need to think like a computer
so I need to check before adding?
thats one way
alternatively we handle that in a... more graceful manner
teach me your ways
okay, so there is a method all dictionaries have that is called...
GetValueOrDefault
it takes in a key, and gives you either the value assocaited with that key, or the default
value for that type
this method is incredibly useful
because we want access to the list for a given category, or a blank list if there is no list already associated
how can we do that?CAN WE??? ofc
?
oh ok, I read it wrong💀
how shamefull
with something like this
ooo, spicy
and not too far off either
categories.GetValueOrDefault(key);
yep
so
that will give you back the value, or
default
for List<int>
which is.... null
Lists default to null
so we combine that with a fancy operator called ??
and presto
var values = categories.GetValueOrDefault(key) ?? [];
now this might be a lot to unpack, so lets go over exactly what it does
we get the value in the dictionary, or null
then ??
checks if the left operand is null... if it is, it assigns the right operand
if it wasnt, it does nothing
so value is either the list we had, or a blank new list []
holy shit
alright then
but doesnt this need IF statement?
this is the same as writing...
nope
thats why its so beautiful
for real
but yeah, there is a conditional in there, its just not an if
regardless
we now have a list
now we can add values to it
suggestions?
we add key to values💀
naww
not key
key is the category
so points?
yep
should I add sum()?
no
again, you chose NOT to work that way
and you are not sure if this is the last time you see this category
so its too early to sum anything
alright
but those mean they are whole ?
I might be slow on this one
they are not entire categories yet
they are categories in progress
they MIGHT be full, or they might not be
we simply dont know
but then again, this line is to check which category has same numbers right?
yeah
kk
if we already have a list, we get that, instead of starting on a new list
lmao
im stuck again
close
but why are you skipping the first point?
and what does
.Add
expect?now that I think about it, I forgot what meant. my mistake
could it be it expects only one item?
soooo whole array doesnt work
correct. is there perhaps another method that expects more?
values.ForEach(x => {points[x]++;}); this thing
naw
values.AddRange
xd
oh ofc
values.AddRange(points); correct?
yep
this might sound dumb, but at this point, program doesnt know which category has duplicates right?
it doesnt know and it doesnt care
it handles them nicely
for example, these two lines
it will essentially see as
1 15 20 22 5 9 9 6 8 7 12
and I can prove it to youbecause of this line right?
yea
well, we are actually not quite done yet
we have 1 more thing to do
we need to update the dictionarys reference for the key
because we might have created a new list
so lets slap a
categories[key] = values;
down therealright
now, the code should look like...
that last part just prints the stuff inside the dictionary
prints this for me:
and I just put Sum() at the end xd
yep
one last thing
sorting
from smallest to biggest category
but idk
nah
so, what do you mean by smallest category? the category id itself, or the summed values?
by var key if I understand
.Sort()
doesnt work on dictionaries, they are unsortable because of how they work. You can however "sort" them when you iterate over their content...
this is second foreach loop right?
yes
console is empty for me somehow
ooh my mistake
fixed
well what can I say
thank you sooooo much my master
for putting up with me today xd
gonna give you a fair warning
if you turn this in to a teacher as "your code"
they will know you did not write this yourself
nahh, this isnt my homework
good
one question tho - how would you rate this task
because while it isnt a masterpiece, its using some fancy stuff, like
??
and GetValueOrDefault
, and []
, and .Select
...how hard is it fomr 1 to 10
the task? its good
well whats a 10?
nasa level orbital calculations?
10 is like, you spend week doing it and 1 is 5 mins of work
hm okay
a 3?
damn xd
I could have done this in 30-40 seconds probably
I need to get better
but I'm not new
ok another question, how long have you been programming?
Ive written C# for over 20 years
ohhhhhhh
and programming in total for... almost 30
explains a lot
yeah 🙂
damn how wonderful
well thx again
do you understand this code now?
or is anything unclear in how it works
looks like everythings clear but to make it perfectly clear, I'll need to work with it
thats fine