convert char dictionary to string dictionary - c#

I have been given a homework with the following statement:
Write a program which counts all characters in a string except space (' ').
Print all occurrences in the following format:
{char} -> {occurrences}
I wrote the program in char, but i keep getting a timeout error when i submit it in their homework-system. Here is my code:
SortedDictionary<char, int> text = new SortedDictionary<char, int>();
char[] characters = Console.ReadLine()
.Where(x => !Char.IsWhiteSpace(x))
.ToArray();
foreach (var character in characters)
{
if (text.ContainsKey(character))
{
text[character]++;
}
else
{
text.Add(character, 1);
}
}
foreach (var character in text.OrderByDescending(x => x.Value))
{
Console.WriteLine($"{character.Key} -> {character.Value}");
}
I can't get my head around on how to read it as a string and still get the result. Here is an example:
"text text text" = t -> 6 e -> 3 x -> 3

So if I understood you correctly, all you need is to get your output right.
This should do the trick:
foreach (var character in text.OrderByDescending(x => x.Value))
{
Console.WriteLine(String.Format("{0}->{1}", character.Key, character.Value));
}

I am not sure your expectation, but if you use string instead of char array can improve performance a little bit:
var text = new SortedDictionary<char, int>();
var inputText = Console.ReadLine();
foreach (var character in inputText)
{
if (character == ' ')
{
continue;
}
if (text.ContainsKey(character))
{
text[character]++;
}
else
{
text.Add(character, 1);
}
}

Related

C# looping through a list to find character counts

I'm trying to loop through a string to find the character, ASCII value, and the number of times the character occurs. So far, I have found each unique character and ASCII value using foreach statements, and finding if the value was already in the list, then don't add it, otherwise add it. However I'm struggling with the count portion. I was thinking the logic would be "if I am already in the list, don't count me again, however, increment my frequency"
I've tried a few different things, such as trying to find the index of the character it found and adding to that specific index, but i'm lost.
string String = "hello my name is lauren";
char[] String1 = String.ToCharArray();
// int [] frequency = new int[String1.Length]; //array of frequency counter
int length = 0;
List<char> letters = new List<char>();
List<int> ascii = new List<int>();
List<int> frequency = new List<int>();
foreach (int ASCII in String1)
{
bool exists = ascii.Contains(ASCII);
if (exists)
{
//add to frequency at same index
//ascii.Insert(1, ascii);
//get { ASCII[index]; }
}
else
{
ascii.Add(ASCII);
//add to frequency at new index
}
}
foreach (char letter in String1)
{
bool exists = letters.Contains(letter);
if (exists)
{
//add to frequency at same index
}
else
{
letters.Add(letter);
//add to frequency at new index
}
}
length = letters.Count;
for (int j = 0; j<length; ++j)
{
Console.WriteLine($"{letters[j].ToString(),3} {"(" + ascii[j] + ")"}\t");
}
Console.ReadLine();
}
}
}
I'm not sure if I understand your question but that what you are looking for may be Dictionary<T,T> instead of List<T>. Here are examples of solutions to problems i think you trying to solve.
Counting frequency of characters appearance
Dictionary<int, int> frequency = new Dictionary<int, int>();
foreach (int j in String)
{
if (frequency.ContainsKey(j))
{
frequency[j] += 1;
}
else
{
frequency.Add(j, 1);
}
}
Method to link characters to their ASCII
Dictionary<char, int> ASCIIofCharacters = new Dictionary<char, int>();
foreach (char i in String)
{
if (ASCIIofCharacters.ContainsKey(i))
{
}
else
{
ASCIIofCharacters.Add(i, (int)i);
}
}
A simple LINQ approach is to do this:
string String = "hello my name is lauren";
var results =
String
.GroupBy(x => x)
.Select(x => new { character = x.Key, ascii = (int)x.Key, frequency = x.Count() })
.ToArray();
That gives me:
If I understood your question, you want to map each char in the provided string to the count of times it appears in the string, right?
If that is the case, there are tons of ways to do that, and you also need to choose in which data structure you want to store the result.
Assuming you want to use linq and store the result in a Dictionary<char, int>, you could do something like this:
static IDictionary<char, int> getAsciiAndFrequencies(string str) {
return (
from c in str
group c by Convert.ToChar(c)
).ToDictionary(c => c.Key, c => c.Count());
}
And use if like this:
var f = getAsciiAndFrequencies("hello my name is lauren");
// result: { h: 1, e: 3, l: 3, o: 1, ... }
You are creating a histogram. But you should not use List.Contains as it gets ineffective as the list grows. You have to go through the list one item after another. Better use Dictionary which is based on hashing and you go directly to the item. The code may look like this
string str = "hello my name is lauren";
var dict = new Dictionary<char, int>();
foreach (char c in str)
{
dict.TryGetValue(c, out int count);
dict[c] = ++count;
}
foreach (var pair in dict.OrderBy(r => r.Key))
{
Console.WriteLine(pair.Value + "x " + pair.Key + " (" + (int)pair.Key + ")");
}
which gives
4x (32)
2x a (97)
3x e (101)
1x h (104)
1x i (105)
3x l (108)
2x m (109)
2x n (110)
1x o (111)
1x r (114)
1x s (115)
1x u (117)
1x y (121)

How to remove space between two words in the same string [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have a string like this
string input = "\r\n\r\nMaster = \r\nSlave\r\nRed =\r\n Blue";
What I want is that Master = Slave, Red= Blue so that I can create a dictionary.
The method that I am trying to use is:
1) String temp= Regex.Replace(str, “/r/n/r/n”, “”);
2) String temp= str.Replace(“/r/n/r/n”, “”);
Both the methods don’t seem to give me the result that I want. I even tried removing the white space but even that didn’t work out. Please help. Thank you.
It sounds like you have a string like this:
string Str = "Master = Slave\r\nRed = Blue";
And for output are you looking for something like this:
var dict = new Dictionary<string, string> { { "Master", "Slave" }, { "Red", "Blue" } };
If so, one way to do this is to first split the string on the newline characters, then split each of those on the equals character, and then add the resulting pair to a dictionary.
For example:
string input = "Master = Slave\r\nRed = Blue";
string[] keyValuePairs = input.Split( '\r', '\n');
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (var keyValuePair in keyValuePairs)
{
var parts = keyValuePair.Split('=');
if (parts.Length > 1)
{
dict.Add(parts[0].Trim(), parts[1].Trim());
}
}
// Result:
// dict
// Count = 2
// [0]: {[Master, Slave]}
// [1]: {[Red, Blue]}
The code above can be shortened using some System.Linq extension methods:
Dictionary<string, string> dict = input
.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries)
.Select(kvp => kvp.Split('='))
.Where(parts => parts.Length > 1)
.ToDictionary(x => x[0].Trim(), x => x[1].Trim());
Another way to do this, since in the comments you've mentioned the newline characters may appear anywhere, is to examine the results after splitting the input on \r\n and splitting the result of that on the = character.
If the result has two parts, we have a key and a value, so add it to the dictionary. If there's only one part, and we haven't saved a key value yet, then save it as a key. Otherwise, add the saved key and this part as the value.
For example:
var input = "\r\n\r\nMaster = \r\nSlave\r\nRed =\r\n Blue";
var dict = new Dictionary<string, string>();
var currentKey = "";
foreach (var item in input.Split(new[] { '\r', '\n' },
StringSplitOptions.RemoveEmptyEntries))
{
var parts = item.Split(new[] { '=' },
StringSplitOptions.RemoveEmptyEntries);
if (currentKey.Length == 0)
{
if (parts.Length > 1 && !string.IsNullOrWhiteSpace(parts[1]))
{
dict.Add(parts[0].Trim(), parts[1].Trim());
}
else
{
currentKey = parts[0].Trim();
}
}
else
{
dict.Add(currentKey, parts.Length > 1
? parts[1].Trim()
: parts[0].Trim());
currentKey = "";
}
}

How to output unique symbols except case c# without LINQ

Output unique symbols ignoring case
IDictionary<char, int> charDict = new Dictionary<char, int>();
foreach (var ch in text)
{
if (!charDict.TryGetValue(ch, out n)) {
charDict.Add(new KeyValuePair<char, int>(ch, 1));
} else
{
charDict[ch]++;
}
}
Appellodppsafs => Apelodsf
And Is it possible not to use LINQ?
Use a HashSet<char> to remember existing characters (that's what Distinct() does internally)
Assuming your input and expected result are type string
string input = "Appellodppsafs";
HashSet<char> crs = new HashSet<char>();
string result = string.Concat(input.Where(x => crs.Add(char.ToLower(x)))); //Apelodsf
You can try this (if you do not have long strings or performance issues):
string str = "Appellodppsafs";
string result = string.Concat(str.Select(s => $"{s}")
.Distinct(StringComparer.InvariantCultureIgnoreCase));
Console.WriteLine(result);
Output:
Apelodsf

C#: Loop over Textfile, split it and Print a new Textfile

I get many lines of String as an Input that look like this. The Input is a String that comes from
theObjects.Runstate;
each #VAR;****;#ENDVAR; represents one Line and one step in the loop.
#VAR;Variable=Speed;Value=Fast;Op==;#ENDVAR;#VAR;Variable=Fabricator;Value=Freescale;Op==;#ENDVAR;
I split it, to remove the unwanted fields, like #VAR,#ENDVAR and Op==.
The optimal Output would be:
Speed = Fast;
Fabricator = Freescale; and so on.
I am able to cut out the #VAR and the#ENDVAR. Cutting out the "Op==" wont be that hard, so thats now not the main focus of the question. My biggest concern right now is,thatI want to print the Output as a Text-File. To print an Array I would have to loop over it. But in every iteration, when I get a new line, I overwrite the Array with the current splitted string. I think the last line of the Inputfile is an empty String, so the Output I get is just an empty Text-File. It would be nice if someone could help me.
string[] w;
Textwriter tw2;
foreach (EA.Element theObjects in myPackageObject.Elements)
{
theObjects.Type = "Object";
foreach (EA.Element theElements in PackageHW.Elements)
{
if (theObjects.ClassfierID == theElements.ElementID)
{
t = theObjects.RunState;
w = t.Replace("#ENDVAR;", "#VAR;").Replace("#VAR;", ";").Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in w)
{
tw2.WriteLine(s);
}
}
}
}
This linq-query gives the exptected result:
var keyValuePairLines = File.ReadLines(pathInputFile)
.Select(l =>
{
l = l.Replace("#VAR;", "").Replace("#ENDVAR;", "").Replace("Op==;", "");
IEnumerable<string[]> tokens = l.Split(new[]{';'}, StringSplitOptions.RemoveEmptyEntries)
.Select(t => t.Split('='));
return tokens.Select(t => {
return new KeyValuePair<string, string>(t.First(), t.Last());
});
});
foreach(var keyValLine in keyValuePairLines)
foreach(var keyVal in keyValLine)
Console.WriteLine("Key:{0} Value:{1}", keyVal.Key, keyVal.Value);
Output:
Key:Variable Value:Speed
Key:Value Value:Fast
Key:Variable Value:Fabricator
Key:Value Value:Freescale
If you want to output it to another text-file with one key-value pair on each line:
File.WriteAllLines(pathOutputFile, keyValuePairLines.SelectMany(l =>
l.Select(kv => string.Format("{0}:{1}", kv.Key, kv.Value))));
Edit according to your question in the comment:
"What would I have to change/add so that the Output is like this. I
need AttributeValuePairs, for example: Speed = Fast; or Fabricator =
Freescale ?"
Now i understand the logic, you have key-value pairs but you are interested only in the values. So every two key-values belong together, the first value of a pair specifies the attibute and the second value the value of that attribute(f.e. Speed=Fast).
Then it's a little bit more complicated:
var keyValuePairLines = File.ReadLines(pathInputFile)
.Select(l =>
{
l = l.Replace("#VAR;", "").Replace("#ENDVAR;", "").Replace("Op==;", "");
string[] tokens = l.Split(new[]{';'}, StringSplitOptions.RemoveEmptyEntries);
var lineValues = new List<KeyValuePair<string, string>>();
for(int i = 0; i < tokens.Length; i += 2)
{
// Value to a variable can be found on the next index, therefore i += 2
string[] pair = tokens[i].Split('=');
string key = pair.Last();
string value = null;
string nextToken = tokens.ElementAtOrDefault(i + 1);
if (nextToken != null)
{
pair = nextToken.Split('=');
value = pair.Last();
}
var keyVal = new KeyValuePair<string, string>(key, value);
lineValues.Add(keyVal);
}
return lineValues;
});
File.WriteAllLines(pathOutputFile, keyValuePairLines.SelectMany(l =>
l.Select(kv=>string.Format("{0} = {1}", kv.Key, kv.Value))));
Output in the file with your single sample-line:
Speed = Fast
Fabricator = Freescale

Count the occurrence of strings in an array [duplicate]

This question already has answers here:
A method to count occurrences in a list
(7 answers)
Counting words in a collection using LINQ
(7 answers)
Closed 9 years ago.
I am counting the how many strings are present in the array-
Tags = "the cat the mat the sat";
string[] words = Tags.Split(' ');
int counter = 0;
foreach (string item in words)
{
if (item != "")
{
counter++;
}
}
However how could I modify my code so that I counted the occurrence of every string.
So for instance -
"the" = 3
"cat" = 1
"mat" = 1
"sat" = 1
and then store these values some way?
You don't say what language you use, but what I see it looks like c#. Here is one way to do it.
Dictionary<string, int> dictionary = new Dictionary<string, int>();
foreach (string word in words)
{
if (dictionary.ContainsKey(word))
{
dictionary[word] += 1;
}
else
{
dictionary.Add(word,1);
}
}
Try this:
var result = tags.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.GroupBy(tag => tag)
.ToDictionary(group => group.Key, group => group.Count());
var max = result.MaxBy(kvp => kvp.Value);
var min = result.MinBy(kvp => kvp.Value);
using MaxBy and MinBy from MoreLINQ.
Store in a map where the key is the word and the value is a counter of how many times it appears....
You must use Dictionary. Here it is:
string Tags = "the cat the mat the sat";
string[] words = Tags.Split(' ');
Dictionary<string, int> oddw = new Dictionary<string, int>();
foreach (string item in words)
{
if (item != "")
{
if (oddw.ContainsKey(item) == false)
{
oddw.Add(item, 1);
}
else
{
oddw[item]++;
}
}
}
foreach (var item in oddw)
{
Console.WriteLine(item);
}

Categories