C# random char between first letter to special char [=] - c#

My problem is with getting values from .txt file.
I have this for example[without enter]:
damage=20 big explosion=50 rangeweapon=50.0
and I want to get these values after "=". Just to make a string[] with something like that:
damage=20
big explosion=50
rangeweapon=50.0
I got some other mechanic but i want to find universal mechanic to get all values into string[] and then just check it in switch.
Thank You.

I have try to solve your problem with regex. I found one solution that is not best solution.
May be it can help or guide you to find best solution.
Please try like this
string operation = "damage=20 big explosion=50 rangeweapon=50.0";
string[] wordText = Regex.Split(operation, #"(\=\d+\.?\d?)");
/*for split word but result array has last value that empty you will delete its*/
string[] wordValue = Regex.Split(operation, #"(\s*\D+\=)"); /*for split digit that is value of word but result array has first value that empty you will delete its*/
After that you can join or do anything you want with those array.

This should parse the string you describe, but keep in mind it isn't very robust and has no error handling.
string stringToParse = "damage=20 big explosion=50 rangeweapon=50.0";
string[] values = stringToParse.Split(' ');
Dictionary<string, double> parsedValues = new Dictionary<string, double>();
string temp = "";
foreach (var value in values)
{
if (value.Contains('='))
{
string[] keyValue = value.Split('=');
parsedValues.Add(temp + keyValue[0], Double.Parse(keyValue[1]));
temp = string.Empty;
}
else
{
temp += value + ' ';
}
}
After this, the parsedValues dictionary should have the information you're looking for.

I'm not an expert about it, but what about using a Regex ?

Not the cleanest code in the world, but will work for your situation.
string input = "damage=20 big explosion=50 rangeweapon=50.0";
string[] parts = input.Split('=');
Dictionary<string, double> dict = new Dictionary<string, double>();
for (int i = 0; i < (parts.Length - 1); i++)
{
string key = i==0?parts[i]:parts[i].Substring(parts[i].IndexOf(' '));
string value = i==parts.Length-2?parts[i+1]:parts[i + 1].Substring(0, parts[i + 1].IndexOf(' '));
dict.Add(key.Trim(), Double.Parse(value));
}
foreach (var el in dict)
{
Console.WriteLine("Key {0} contains value {1}", el.Key, el.Value);
}
Console.ReadLine();

You want to read number from text.You can save your data in text like this.
damage=20,big explosion=50,rangeweapon=50. And read from text via File.ReadAllLines().
string[] Lines;
string[] myArray;
Lines = File.ReadAllLines(your file path);
for (int i = 0; i < Lines.Length; i++)
{
myArray = Lines[i].Split(',');
}
for (int j = 0; j < myArray .Length; j++)
{
string x =myArray [j].ToString();
x = Regex.Replace(x, "[^0-9.]", "");
Console.WriteLine(x);
}

Related

Detecting and modifying ListBox entries that contain digits

My program has about 25 entries, most of them string only. However, some of them are supposed to have digits in them, and I don't need those digits in the output (output should be string only). So, how can I "filter out" integers from strings?
Also, if I have integers, strings AND chars, how could I do it (for example, one ListBox entry is E#2, and should be renamed to E# and then printed as output)?
Assuming that your entries are in a List<string>, you can loop through the list and then through each character of each entry, then check if it is a number and remove it. Something like this:
List<string> list = new List<string>{ "abc123", "xxx111", "yyy222" };
for (int i = 0; i < list.Count; i++) {
var no_numbers = "";
foreach (char c in list[i]) {
if (!Char.IsDigit(c))
no_numbers += c;
}
list[i] = no_numbers;
}
This only removes digits as it seems you wanted from your question. If you want to remove all other characters except letters, you can change the logic a bit and use Char.IsLetter() instead of Char.IsDigit().
You can remove all numbers from a strings with this LINQ solution:
string numbers = "Ho5w ar7e y9ou3?";
string noNumbers = new string(numbers.Where(c => !char.IsDigit(c)).ToArray());
noNumbers = "How are you?"
But you can also remove all numbers from a string by using a foreach loop :
string numbers = "Ho5w ar7e y9ou3?";
List<char> noNumList = new List<char>();
foreach (var c in numbers)
{
if (!char.IsDigit(c))
noNumList.Add(c);
}
string noNumbers = string.Join("", noNumList);
If you want to remove all numbers from strings inside a collection :
List<string> myList = new List<string>() {
"Ho5w ar7e y9ou3?",
"W9he7re a3re y4ou go6ing?",
"He2ll4o!"
};
List<char> noNumList = new List<char>();
for (int i = 0; i < myList.Count; i++)
{
foreach (var c in myList[i])
{
if(!char.IsDigit(c))
noNumList.Add(c);
}
myList[i] = string.Join("", noNumList);
noNumList.Clear();
}
myList Output :
"How are you?"
"Where are you going?"
"Hello!"
I don't know exactly what is your scenario, but given a string, you can loop through its characters, and if it's a number, discard it from output.
Maybe this is what you're looking for:
string entry = "E#2";
char[] output = new char[entry.Length];
for(int i = 0, j =0; i < entry.Length ; i++)
{
if(!Char.IsDigit(entry[i]))
{
output[j] = entry[i];
j++;
}
}
Console.WriteLine(output);
I've tried to give you a simple solution with one loop and two index variables, avoiding string concatenations that can make performance lacks.
See this example working at C# Online Compiler
If i am not wrong,maybe this is how your list looks ?
ABCD123
EFGH456
And your expected output is :
ABCD
EFGH
Is that correct?If so,assuming that it's a List<string>,then you can use the below code :
list<string> mylist = new list<string>;
foreach(string item in mylist)
{
///To get letters/alphabets
var letters = new String(item.Where(Char.IsLetter).ToArray());
///to get special characters
var letters = new String(item.Where(Char.IsSymbol).ToArray())
}
Now you can easily combine the codes :)

Replace string with multiple different options

Hi there wonderful people of stackOverFlow.
I am currently in a position where im totaly stuck. What i want to be able to do is take out a word from a text and replace it with a synonym. I thought about it for a while and figured out how to do it if i ONLY have one possible synonym with this code.
string pathToDesk = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string text = System.IO.File.ReadAllText(pathToDesk + "/Text.txt");
string replacementsText = System.IO.File.ReadAllText(pathToDesk + "/Replacements.txt");
string wordsToReplace = System.IO.File.ReadAllText(pathToDesk + "/WordsToReplace.txt");
string[] words = text.Split(' ');
string[] reWords = wordsToReplace.Split(' ');
string[] replacements = replacementsText.Split(' ');
for(int i = 0; i < words.Length; i++) {//for each word
for(int j = 0; j < replacements.Length; j++) {//compare with the possible synonyms
if (words[i].Equals(reWords[j], StringComparison.InvariantCultureIgnoreCase)) {
words[i] = replacements[j];
}
}
}
string newText = "";
for(int i = 0; i < words.Length; i++) {
newText += words[i] + " ";
}
txfInput.Text = newText;
But lets say that we were to get the word hi. Then i want to be able to replace that with {"Hello","Yo","Hola"}; (For example)
Then my code will not be good for anything since they will not have the same position in the arrays.
Is there any smart solution to this I would really like to know.
you need to store your synonyms differently
in your file you need something like
hello yo hola hi
awesome fantastic great
then for each line, split the words, put them in an array array of arrays
Now use that to find replacement words
This won't be super optimized, but you can easily index each word to a group of synonyms as well.
something like
public class SynonymReplacer
{
private Dictionary<string, List<string>> _synonyms;
public void Load(string s)
{
_synonyms = new Dictionary<string, List<string>>();
var lines = s.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var words = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries).ToList();
words.ForEach(word => _synonyms.Add(word, words));
}
}
public string Replace(string word)
{
if (_synonyms.ContainsKey(word))
{
return _synonyms[word].OrderBy(a => Guid.NewGuid())
.FirstOrDefault(w => w != word) ?? word;
}
return word;
}
}
The OrderBy gets you a random synonym...
then
var s = new SynonymReplacer();
s.Load("hi hello yo hola\r\nawesome fantastic great\r\n");
Console.WriteLine(s.Replace("hi"));
Console.WriteLine(s.Replace("ok"));
Console.WriteLine(s.Replace("awesome"));
var words = new string[] {"hi", "you", "look", "awesome"};
Console.WriteLine(string.Join(" ", words.Select(s.Replace)));
and you get :-
hello
ok
fantastic
hello you look fantastic
Your first task will be to build a list of words and synonyms. A Dictionary will be perfect for this. The text file containing this list might look like this:
word1|synonym11,synonym12,synonym13
word2|synonym21,synonym22,synonym23
word3|synonym31,synonym32,synonym33
Then you can construct the dictionary like this:
public Dictionary<string, string[]> GetSynonymSet(string synonymSetTextFileFullPath)
{
var dict = new Dictionary<string, string[]>();
string line;
// Read the file and display it line by line.
using (var file = new StreamReader(synonymSetTextFileFullPath))
{
while((line = file.ReadLine()) != null)
{
var split = line.Split('|');
if (!dict.ContainsKey(split[0]))
{
dict.Add(split[0], split[1].Split(','));
}
}
}
return dict;
}
The eventual code will look like this
public string ReplaceWordsInText(Dictionary<string, string[]> synonymSet, string text)
{
var newText = new StringBuilder();
string[] words = text.Split(' ');
for (int i = 0; i < words.Length; i++) //for each word
{
string[] synonyms;
if (synonymSet.TryGetValue(words[i], out synonyms)
{
// The exact synonym you wish to use is up to you.
// I will just use the first one
words[i] = synonyms[0];
}
newText.AppendFormat("{0} ", words[i]);
}
return newText.ToString();
}

split string in to several strings at specific points

I have a text file with lines of text laid out like so
12345MLOL68
12345MLOL68
12345MLOL68
I want to read the file and add commas to the 5th point, 6th point and 9th point and write it to a different text file so the result would be.
12345,M,LOL,68
12345,M,LOL,68
12345,M,LOL,68
This is what I have so far
public static void ToCSV(string fileWRITE, string fileREAD)
{
int count = 0;
string x = "";
StreamWriter commas = new StreamWriter(fileWRITE);
string FileText = new System.IO.StreamReader(fileREAD).ReadToEnd();
var dataList = new List<string>();
IEnumerable<string> splitString = Regex.Split(FileText, "(.{1}.{5})").Where(s => s != String.Empty);
foreach (string y in splitString)
{
dataList.Add(y);
}
foreach (string y in dataList)
{
x = (x + y + ",");
count++;
if (count == 3)
{
x = (x + "NULL,NULL,NULL,NULL");
commas.WriteLine(x);
x = "";
count = 0;
)
}
commas.Close();
}
The problem I'm having is trying to figure out how to split the original string lines I read in at several points. The line
IEnumerable<string> splitString = Regex.Split(FileText, "(.{1}.{5})").Where(s => s != String.Empty);
Is not working in the way I want to. It's just adding up the 1 and 5 and splitting all strings at the 6th char.
Can anyone help me split each string at specific points?
Simpler code:
public static void ToCSV(string fileWRITE, string fileREAD)
{
string[] lines = File.ReadAllLines(fileREAD);
string[] splitLines = lines.Select(s => Regex.Replace(s, "(.{5})(.)(.{3})(.*)", "$1,$2,$3,$4")).ToArray();
File.WriteAllLines(fileWRITE, splitLines);
}
Just insert at the right place in descending order like this.
string str = "12345MLOL68";
int[] indices = {5, 6, 9};
indices = indices.OrderByDescending(x => x).ToArray();
foreach (var index in indices)
{
str = str.Insert(index, ",");
}
We're doing this in descending order because if we do other way indices will change, it will be hard to track it.
Here is the Demo
Why don't you use substring , example
editedstring=input.substring(0,5)+","+input.substring(5,1)+","+input.substring(6,3)+","+input.substring(9);
This should suits your need.

How to replace characters in a string?

I want to replace characters in a string content in file.
Below Dictionary shows the Key as unwanted character and i need to replace with the value in the Dictionary.
Dictionary<string, string> unwantedCharacters = new Dictionary<string, string>();
unwantedCharacters["É"] = "#";
unwantedCharacters["Ä"] = "[";
unwantedCharacters["Ö"] = "\\";
unwantedCharacters["Å"] = "]";
unwantedCharacters["Ü"] = "^";
unwantedCharacters["é"] = "`";
unwantedCharacters["ä"] = "{";
unwantedCharacters["ö"] = "|";
unwantedCharacters["å"] = "}";
unwantedCharacters["ü"] = "~";
Here is the code i currently using,Feel like its taking too much execution time..
for (int index = 0; index < fileContents.Length; index++)
{
foreach (KeyValuePair<string, string> item in unwantedCharacters)
{
if (fileContents.IndexOf(item.Key) > -1)
{
fileContents = fileContents.Replace(item.Key, item.Value); // Replacing straight characters
}
}
}
ie,Looping in two levels.. Any other ways implement this..Any help will be appreciated
Since you're not modifying the length of the string, if you make unwantedCharacters a Dictionary<char, char> rather than <string, string>, you can do the following:
var charArray = fileContents.ToCharArray();
for (int i = 0; i < charArray.Length; i++)
{
char replacement;
if (unwantedCharacters.TryGetValue(charArray[i], out replacement))
charArray[i] = replacement;
}
fileContents = new string(charArray);
Performance is O(n) in releation to the length of the input string.
It seems fileContents is a string value here. You could simply call replace on the string.
foreach (KeyValuePair<string, string> item in unwantedCharacters)
{
fileContents = fileContents.Replace(item.Key, item.Value);
}
Look this answer: answer
But in this code put your characteres:
IDictionary<string,string> map = new Dictionary<string,string>()
{
{"É", = "#"},
{"Ä", = "["},
{"Ö", = "\\"},
...
};
In order to replace many characters in string, consider to use StringBuilder Class. Replacing one character in string causes in creation of entirly new string so it is highly inefficient. Try the below:
var sb = new StringBuilder(fileContents.Length);
foreach (var c in fileContents)
sb.Append(unwantedCharacters.ContainsKey(c) ? unwantedCharacters[c] : c);
fileContents = sb.ToString();
I assumed here, that your dictionary contains characters (Dictionary<char, char>). It it is a case, just comment and I will edit the solution.
I also assumed, that fileContents is a string.
You can also use LINQ instead of StringBuilder:
var fileContentsEnumerable = from c in fileContents
select unwantedCharacters.ContainsKey(c) ? unwantedCharacters[c] : c;
fileContents = new string(fileContentsEnumerable.ToArray());
You want to build a filter. You process the contents of the file, and do the substitution while you process it.
Something like this:
using(StreamReader reader = new StreamReader("filename"))
using (StreamWriter writer = new StreamWriter("outfile"))
{
char currChar = 0;
while ((currChar = reader.Read()) >= 0)
{
char outChar = unwantedCharacters.ContainsKey(currChar)
? unwantedCharacters[currChar]
: (char) currChar;
writer.Write(outChar);
}
}
You can use a memeory stream if your data is in memory, or a loop through fileContents is that's a string or char array.
This solution is O(n) where n is the length of the file, thanks to the dictionary (note that you could use a simple sparse array instead of the dictionary and you would gain quite a bit of speed).
Do not iterate through the dictionary as other suggest as each substitution is O(n) so you end up with a total time of O(n*d), d being the dictionary size, as you have to go through the file many times.
Remove the foreach and replace with a for loop from 0 to item.Count. This article will help, hopefully.

Need some help on a Regex match / replace pattern

My ultimate goal here is to turn the following string into JSON, but I would settle for something that gets me one step closer by combining the fieldname with each of the values.
Sample Data:
Field1:abc;def;Field2:asd;fgh;
Using Regex.Replace(), I need it to at least look like this:
Field1:abc,Field1:def,Field2:asd,Field2:fgh
Ultimately, this result would be awesome if it can be done via Regex in a single call.
{"Field1":"abc","Field2":"asd"},{"Field1":"def","Field2":"fgh"}
I've tried many different variations of this pattern, but can't seem to get it right:
(?:(\w+):)*?(?:([^:;]+);)
Only one other example I could find that is doing something similar, but just enough differences that I can't quite put my finger on it.
Regex to repeat a capture across a CDL?
EDIT:
Here's my solution. I'm not going to post it as a "Solution" because I want to give credit to one that was posted by others. In the end, I took a piece from each of the posted solutions and came up with this one. Thanks to everyone who posted. I gave credit to the solution that compiled, executed fastest and had the most accurate results.
string hbi = "Field1:aaa;bbb;ccc;ddd;Field2:111;222;333;444;";
Regex re = new Regex(#"(\w+):(?:([^:;]+);)+");
MatchCollection matches = re.Matches(hbi);
SortedDictionary<string, string> dict = new SortedDictionary<string, string>();
for (int x = 0; x < matches.Count; x++)
{
Match match = matches[x];
string property = match.Groups[1].Value;
for (int i = 0; i < match.Groups[2].Captures.Count; i++)
{
string key = i.ToString() + x.ToString();
dict.Add(key, string.Format("\"{0}\":\"{1}\"", property, match.Groups[2].Captures[i].Value));
}
}
Console.WriteLine(string.Join(",", dict.Values));
Now you have two problems
I don't think regular expressions will be the best way to handle this. You should probably start by splitting on semicolons, then loop through the results looking for a value that starts with "Field1:" or "Field2:" and collect the results into a Dictionary.
Treat this as pseudo code because I have not compiled or tested it:
string[] data = input.Split(';');
dictionary<string, string> map = new dictionary<string, string>();
string currentKey = null;
foreach (string value in data)
{
// This part should change depending on how the fields are defined.
// If it's a fixed set you could have an array of fields to search,
// or you might need to use a regular expression.
if (value.IndexOf("Field1:") == 0 || value.IndexOf("Field2:"))
{
string currentKey = value.Substring(0, value.IndexOf(":"));
value = value.Substring(currentKey.Length+1);
}
map[currentKey] = value;
}
// convert map to json
I had an idea that it should be possible to do this in a shorter and more clear way. It ended up not being all that much shorter and you can question if it's more clear. At least it's another way to solve the problem.
var str = "Field1:abc;def;Field2:asd;fgh";
var rows = new List<Dictionary<string, string>>();
int index = 0;
string value;
string fieldname = "";
foreach (var s in str.Split(';'))
{
if (s.Contains(":"))
{
index = 0;
var tmp = s.Split(':');
fieldname = tmp[0];
value = tmp[1];
}
else
{
value = s;
index++;
}
if (rows.Count < (index + 1))
rows.Insert(index, new Dictionary<string, string>());
rows[index][fieldname] = value;
}
var arr = rows.Select(dict =>
String.Join("," , dict.Select(kv =>
String.Format("\"{0}\":\"{1}\"", kv.Key, kv.Value))))
.Select(r => "{" + r + "}");
var json = String.Join(",", arr );
Debug.WriteLine(json);
Outputs:
{"Field1":"abc","Field2":"asd"},{"Field1":"def","Field2":"fgh"}
I would go with RegEx as the simplest and most straightforward way to parse the strings, but I'm sorry, pal, I couldn't come up with a clever-enough replacement string to do this in one shot.
I hacked it out for fun through, and the monstrosity below accomplishes what you need, albeit hideously. :-/
Regex r = new Regex(#"(?<FieldName>\w+:)*(?:(?<Value>(?:[^:;]+);)+)");
var matches = r.Matches("Field1:abc;def;Field2:asd;fgh;moo;"); // Modified to test "uneven" data as well.
var tuples = new[] { new { FieldName = "", Value = "", Index = 0 } }.ToList(); tuples.Clear();
foreach (Match match in matches)
{
var matchGroups = match.Groups;
var fieldName = matchGroups[1].Captures[0].Value;
int index = 0;
foreach (Capture cap in matchGroups[2].Captures)
{
var tuple = new { FieldName = fieldName, Value = cap.Value, Index = index };
tuples.Add(tuple);
index++;
}
}
var maxIndex = tuples.Max(tup => tup.Index);
var jsonItemList = new List<string>();
for (int a = 0; a < maxIndex+1; a++)
{
var jsonBuilder = new StringBuilder();
jsonBuilder.Append("{");
foreach (var tuple in tuples.Where(tup => tup.Index == a))
{
jsonBuilder.Append(string.Format("\"{0}\":\"{1}\",", tuple.FieldName, tuple.Value));
}
jsonBuilder.Remove(jsonBuilder.Length - 1, 1); // trim last comma.
jsonBuilder.Append("}");
jsonItemList.Add(jsonBuilder.ToString());
}
foreach (var item in jsonItemList)
{
// Write your items to your document stream.
}

Categories

Resources