Please read the specifics below:
I have a string array as so:
string[] data = new string[] { "word1", "word2", "word3" };
I'm trying to put a STRING variable, which will include the "word1", "word2", "word3" data, inside of the string array.
In other words, I want the string array to look as so:
SingleStringHere = "\"word1\", \"word2\", \"word3\"";
string[] data = new string[] { SingleStringHere };
The 'SingleStringHere' variable will be retrieving data off of a server, which will be used in the string array. The string array will be formatted and encrypted properly, in order to be sent in a packet through a socket.
No errors are given with the code, however, data in the 'SingleStringHere' variable is not being read as separate strings. I do NOT want to put the retrieved server data into a string array, because that will be TOO MUCH parsing!
If the strings that you receive don't contain commas, you could do something as simple as this:
string SingleStringHere = "\"word1\", \"word2\", \"word3\"";
string[] data = SingleStringHere.Replace("\"").Split(',');
Otherwise, you're going to have to do some more complex parsing. Something like this:
static void Main(string[] args)
{
string SingleStringHere = "\"word1\", \"word2\", \"word3\"";
string[] data = ParseSingleString(SingleStringHere);
foreach(string s in data)
{
Console.WriteLine(s);
}
}
public static string[] ParseSingleString(string singleString)
{
List<string> multipleStrings = new List<string>();
StringBuilder current = new StringBuilder();
bool inQuote = false;
for(int index = 0; index < singleString.Length; ++index) // iterate through the string
{
if (singleString[index] == '"')
{
inQuote = !inQuote;
}
else if (!inQuote && singleString[index] == ',') // split at comma if not in quote
{
multipleStrings.Add(current.ToString().Trim());
current.Clear();
}
else
{
current.Append(singleString[index]);
}
}
multipleStrings.Add(current.ToString()); // don't forget the last one
return multipleStrings.ToArray();
}
If the strings can contain quotes, it can get trickier. That's just my rough example.
Be warned that this operation might be memory-intensive with all of the string copying and so forth (I count about 3 copies for each substring). You may be able to circumvent some of this by recording the indices of the first and last character in one of the strings, and then taking a substring on the entire singleString. Also note that List<string> has to be copied into an array before it returns. You may want to just return an IEnumerable<string> instead, or even an IList<string>. But it's late, and I think the above is sufficient for this question.
P.s. I'm on a Linux machine right now without access to a C# compiler, so I apologize for any typos.
You can get array from formatted string like this
string SingleStringHere = "\"word1\", \"word2\", \"word3\"";
String[] arr = SingleStringHere.Split(',');
Related
I was trying to create a list from a user input with something like this:
Create newlist: word1, word2, word3, etc...,
but how do I get those words one by one only by using commas as references going through them (in order) and placing them into an Array etc? Example:
string Input = Console.ReadLine();
if (Input.Contains("Create new list:"))
{
foreach (char character in Input)
{
if (character == ',')//when it reach a comma
{
//code goes here, where I got stuck...
}
}
}
Edit: I didn`t know the existence of "Split" my mistake... but at least it would great if you could explain me to to use it for the problem above?
You can use this:
String words = "word1, word2, word3";
List:
List<string> wordsList= words.Split(',').ToList<string>();
Array:
string[] namesArray = words.Split(',');
#patrick Artner beat me to it, but you can just split the input with the comma as the argument, or whatever you want the argument to be.
This is the example, and you will learn from the documentation.
using System;
public class Example {
public static void Main() {
String value = "This is a short string.";
Char delimiter = 's';
String[] substrings = value.Split(delimiter);
foreach (var substring in substrings)
Console.WriteLine(substring);
}
}
The example displays the following output:
Thi
i
a
hort
tring.
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 5 years ago.
Improve this question
I am trying to find out if a .txt file contains words stored in a list named Abreviated. This list is filled by reading values from a csv file as shown below;
StreamReader sr = new StreamReader(#"C:\textwords.csv");
string TxtWrd = sr.ReadLine();
while ((TxtWrd = sr.ReadLine()) != null)
{
Words = TxtWrd.Split(Seperators, StringSplitOptions.None);
Abreviated.Add(Words[0]);
Expanded.Add(Words[1]);
}
I would like to use this list to check if a .txt file contains any of the words in the list. The .txt file is being read using a streamreader and is stored as a string FileContent. the code i have to try and find the matches is below;
if (FC.Contains(Abreviated.ToString()))
{
MessageBox.Show("Match found");
}
else
{
MessageBox.Show("No Match");
}
This will always return the else statement even though one of the words is in the text file.
any advice on how to get this working?
Thanks in advance!
You can use key-value pair data structure for storing abbreviated word and respective full word as key-value pair. In C#, Dictionary has generic implementation for storing key value pair.
I've refactored your code which makes easy to reuse.
internal class FileParser
{
internal Dictionary<string, string> WordDictionary = new Dictionary<string, string>();
private string _filePath;
private char Seperators => ',';
internal FileParser(string filePath)
{
_filePath = filePath;
}
internal void Parse()
{
StreamReader sr = new StreamReader(_filePath);
string TxtWrd = sr.ReadLine();
while ((TxtWrd = sr.ReadLine()) != null)
{
var words = TxtWrd.Split(Seperators, StringSplitOptions.None);
//WordDictionary.TryAdd(Words[0], Words[1]); // available in .NET corefx https://github.com/dotnet/corefx/issues/1942
if (!WordDictionary.ContainsKey(words[0]))
WordDictionary.Add(words[0], words[1]);
}
}
internal bool IsWordAvailable(string word)
{
return WordDictionary.ContainsKey(word);
}
}
Now, you can reuse above class within your assembly like in following way :
public class Program
{
public static void Main(string[] args)
{
var fileParser = new FileParser(#"C:\textwords.csv");
if(fileParser.IsWordAvailable("abc"))
{
MessageBox.Show("Match found");
}
else
{
MessageBox.Show("No Match");
}
}
}
You are comparing your entire file's content to the string representation of a collections of words. You need to compare each individual word found in the file content to your abbreviated list. One way you could do the comparison is to split the file content into individual words and then look those up individually against your abbreviated list.
string[] fileWords = FC.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
bool hasMatch = false;
for(string fileWord : fileWords)
{
if(Abbreviated.Contains(fileWord))
{
hasMatch = true;
break;
}
}
if (hasMatch)
{
MessageBox.Show("Match found");
}
else
{
MessageBox.Show("No Match");
}
I would recommend switching your abbreviated collection to a HashSet or a Dictionary that also includes your matching expanded text for the abbreviation. Also, there are probably alternate ways to do the search you are looking for with regex.
I'm unsure on what some of your variables are so this may be slightly different to what you have, but gives the same functionality.
static void Main(string[] args)
{
List<string> abbreviated = new List<string>();
List<string> expanded = new List<string>();
StreamReader sr = new StreamReader("textwords.csv");
string TxtWrd = "";
while ((TxtWrd = sr.ReadLine()) != null)
{
Debug.WriteLine("line: " + TxtWrd);
string[] Words = TxtWrd.Split(new char[] { ',' } , StringSplitOptions.None);
abbreviated.Add(Words[0]);
expanded.Add(Words[1]);
}
if (abbreviated.Contains("wuu2"))
{
//show message box
} else
{
//don't
}
}
As mentioned in one of the comments, a Dictionary might be better suited for this.
This assumes that the data in your file is in the following format, with a new set on each line.
wuu2,what are you up to
If all you want to do is check if a text file contains words in your list, you can read the entire contents of the file into a string (instead of line by line), split the string on your separators, and then check if the intersection of the words in the text file and your list of words has any items:
// Get the "separators" into a list
var wordsFile = #"c:\public\temp\textWords.csv"; // (#"C:\textwords.csv");
var separators = File.ReadAllText(wordsFile).Split(',');
// Get the words of the file into a list (add more delimeters as necessary)
var txtFile = #"c:\public\temp\temp.txt";
var allWords = File.ReadAllText(txtFile).Split(new[] {' ', '.', ',', ';', ':', '\r', '\n'});
// Get the intersection of the file words and the separator words
var commonWords = allWords.Intersect(separators).ToList().Distinct();
if (commonWords.Any())
{
Console.WriteLine("The text file contains the following matching words:");
Console.WriteLine(string.Join(", ", commonWords));
}
else
{
Console.WriteLine("The file did not contain any matching words.");
}
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
I'm Learning c# and i am making some exercises. i was asked to make a program that make an array of strings and remove the vowels form it's words
i did this code to remove the vowel "S" but it didn't work. can someone help me with that ?
string[] musicinst = new string[4] { "cello", "guitar", "violin", "double bass" };
foreach (string s in musicinst)
{
if (s.Contains("s")) { s.Replace("s", ""); }
Console.WriteLine(s);
}
now this code outputs the words exactly as i typed them in the array with no changes. so what is the problem here ?
.Replace does not change the string but returns a new string with the change. You need to now assign it back to s:
if (s.Contains("s"))
{
s = s.Replace("s", "o");
}
This will now also not work:
Cannot assign to 's' because it is a 'foreach iteration variable'
So instead use a for loop and access by indexer or create a new list and add the result of s.Replace to it:
string[] musicinst = new string[4] { "cello", "guitar", "violin", "double bass" };
var newData = musicinst.Select(item => item.Replace("s", "o")).ToArray();
If you need to deal with replacement when insensitive then look at:
Is there an alternative to string.Replace that is case-insensitive?
You're running into a feature of C# strings called immutability - operations on strings do not change the string, it returns a new string. given this, you might think you need to do this:
s = s.Replace("s", "o");
But that won't work because 's' is a foreach iterator. Your best bet is to recast your loop:
for (int i = 0; i < musicinst.Length; ++i)
{
if (musicinst[i].Contains("s"))
{
musicinst[i] = musicinst.Replace("s", "o");
}
}
Which will change your array in-place. To preserve immutability of the array as well you might consider a LINQ-like option that builds a new array as others have demonstrated.
static void Main(string[] args)
{
string[] musicinst = new string[4] { "cello", "guitar", "violin", "double bass" };
char[] vowels = new char[5] { 'a', 'e', 'i' ,'o', 'u' };
List<string> output = new List<string>();
foreach (string s in musicinst)
{
string s1 = s;
foreach (var v in vowels)
{
if (s1.Contains(v))
{
s1=s1.Remove(s1.IndexOf(v),1);
}
}
output.Add(s1);
}
Console.ReadLine();
}
Whenever you perform any operation on a string data type, it creates a new string which you have to store in a new variable.
Is there any method that I can use that returns a fixed length array after spliting a string with some delimiter and fill the rest with a default string.
Eg.
string fullName = "Jhon Doe";
string[] names = fullName.SpecialSplit(some parameters); //This should always return string array of length 3 with the second elememnt set to empty if there is no middle name.
Next time specify the language you're asking about. We're no guessers.
In Java:
fullName.split(" ");
And anyway, no method will "return string array of length 3 with the second elememnt set to empty if there is no middle name". For the method, there are just two elements. You have to write that method yourself wrapping the standard split() method.
You should read over Jon Skeet's Writing the perfect question. It will be beneficial to you in the future when posting questions of StackOverflow.
There is no method in C# to do what you are asking, but you can easily write an extension method to do what I think you are asking.
here is a quick example:
public static class AbreviatorExtention
{
public static string[] GetInitials(this String str, char splitChar)
{
string[] initialArray = new string[3];
var nameArray = str.Split(new char[] { splitChar },
StringSplitOptions.RemoveEmptyEntries);
if (nameArray.Length == 2)
{
var charArrayFirstName = nameArray[0].ToCharArray();
var charArrayLastName = nameArray[1].ToCharArray();
initialArray[0] = charArrayFirstName[0].ToString().ToUpper();
initialArray[1] = string.Empty;
initialArray[2] = charArrayLastName[0].ToString().ToUpper();
}
else
{
for (int i = 0; i < nameArray.Length; i++)
{
initialArray[i] = (nameArray[i].ToCharArray())[1]
.ToString().ToUpper();
}
}
return initialArray;
}
}
class Program
{
static void Main(string[] args)
{
string FullName = "john doe";
//Extension method in use
string[] names = FullName.GetInitials(' ');
foreach (var item in names)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
Output:
J
D
I would set it up to split the string separate from the fixed array. If you still want a fixed array, then you set up the array to a size of three an populate. This is not the best method, however, as it has no meaning. Better, set up a person or user class and then populate, via rules, from the split string.
How can I remove duplicate substrings within a string? so for instance if I have a string like smith:rodgers:someone:smith:white then how can I get a new string that has the extra smith removed like smith:rodgers:someone:white. Also I'd like to keep the colons even though they are duplicated.
many thanks
string input = "smith:rodgers:someone:smith:white";
string output = string.Join(":", input.Split(':').Distinct().ToArray());
Of course this code assumes that you're only looking for duplicate "field" values. That won't remove "smithsmith" in the following string:
"smith:rodgers:someone:smithsmith:white"
It would be possible to write an algorithm to do that, but quite difficult to make it efficient...
Something like this:
string withoutDuplicates = String.Join(":", myString.Split(':').Distinct().ToArray());
Assuming the format of that string:
var theString = "smith:rodgers:someone:smith:white";
var subStrings = theString.Split(new char[] { ':' });
var uniqueEntries = new List<string>();
foreach(var item in subStrings)
{
if (!uniqueEntries.Contains(item))
{
uniqueEntries.Add(item);
}
}
var uniquifiedStringBuilder = new StringBuilder();
foreach(var item in uniqueEntries)
{
uniquifiedStringBuilder.AppendFormat("{0}:", item);
}
var uniqueString = uniquifiedStringBuilder.ToString().Substring(0, uniquifiedStringBuilder.Length - 1);
Is rather long-winded but shows the process to get from one to the other.
not sure why you want to keep the duplicate colons. if you are expecting the output to be "smith:rodgers:someone::white" try this code:
public static string RemoveDuplicates(string input)
{
string output = string.Empty;
System.Collections.Specialized.StringCollection unique = new System.Collections.Specialized.StringCollection();
string[] parts = input.Split(':');
foreach (string part in parts)
{
output += ":";
if (!unique.Contains(part))
{
unique.Add(part);
output += part;
}
}
output = output.Substring(1);
return output;
}
ofcourse i've not checked for null input, but i'm sure u'll do it ;)