Splitting string on unique partrs, sort and concatenate again - c#

I'm just learning C#, so please don't blame me if the solution is obvious.
I have comma-delimeted string. I want to split it, remove duplicates from splitted array, sort result array and then concatenate again.
E.g. for string "3,a,b,3,a,c,s,3,1,2,3,3" result should be: "1,2,3,a,b,c,s"
What I've tried so far is next code:
static void Main(string[] args)
{
string myStr = "3,a,b,3,a,c,s,3,1,2,3,3";
string[] temp = myStr.Split(',');
string res = "";
List<string> myList = new List<string>();
foreach (var t in temp)
{
if (myList.Contains(t)==false){
myList.Add(t);
}
}
myList.Sort();
foreach(var t in myList){
res+=t +",";
}
res = res.Substring(0, res.Length - 1);
Console.WriteLine(res);
}
But I believe there is more effificent way..
Thanks in advise.

Try this single line:
Console.WriteLine(string.Join(",",myStr.Split(',').Distinct().OrderBy(x=>x)));

Related

Get first word on every new line in a long string?

I am trying to add a leaderboard in my unity app
I have a long string as below(just an example, actual string is http pipe data from my web service, not manually stored):
string str ="name1|10|junk data.....\n
name2|9|junk data.....\n
name3|8|junk data.....\n
name4|7|junk data....."
I want to get the first word (string before the first pipe '|' like name1,name2...) from every line and store it in an array and then get the numbers (10,9,8... arter the '|') and store it in an other one.
Anyone know whats the best way to do this?
Fiddle here: https://dotnetfiddle.net/utp4HK
code below, you may want to revisit the algorithm for performance, but if that is not an issue, this will do the trick;
using System;
public class Program
{
public static void Main()
{
string str ="name1|10|junk data.....\nname2|9|junk data.....\nname3|8|junkdata.....\nname4|7|junk data.....";
foreach (var line in str.Split('\n'))
{
Console.WriteLine(line.Split('|')[0]);
}
}
}
First split by new-line characters:
string[] lines = str.Split(new string[]{Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
Then you can use LINQ to get both arrays:
var data = lines.Select(l => l.Trim().Split('|')).Where(arr => arr.Length > 1);
string[] names = data.Select(arr => arr[0].Trim()).ToArray();
string[] numbers = data.Select(arr => arr[1].Trim()).ToArray();
Check out this link on splitting strings: http://msdn.microsoft.com/en-us/library/ms228388.aspx
You could first create an array of strings (one for each line) by splitting the long string with \n as the delimeter.
Then, you could split each line with | as the delimeter. The name would be the 0th index of the array and the number would be the 1st index of the array.
First of all, you can't have a multi line string without using verbatim string literal. With using verbatim string literal, you can split your string based on \r\n or Environment.NewLine like;
string str = #"name1|10|junk data.....
name2|9|junk data.....
name3|8|junk data.....
name4|7|junk data.....";
var array = str.Split(new []{Environment.NewLine},
StringSplitOptions.RemoveEmptyEntries);
foreach (var item in array)
{
Console.WriteLine(item.Split(new[]{"|"},
StringSplitOptions.RemoveEmptyEntries)[0].Trim());
}
Output will be;
name1
name2
name3
name4
Try this:
string str ="name1|10|junk data.....\n" +
"name2|9|junk data.....\n" +
"name3|8|junk data.....\n" +
"name4|7|junk data.....";
string[] tempArray1 = str.Split('\n');
string[] tempArray2 = null;
string[,] newArray = null;
for (int i = 0; i < tempArray1.Length; i++)
{
tempArray2 = tempArray1[i].Split('|');
if (newArray[0, 0].ToString().Length == 0)
{
newArray = new string[tempArray1.Length, tempArray2.Length];
}
for (int j = 0; j < tempArray2.Length; j++)
{
newArray[i,j] = tempArray2[j];
}
}

Replace every other of a certain char in a string

I have searched a lot to find a solution to this, but could not find anything. I do however suspect that it is because I don't know what to search for.
First, I have a string that I convert to an array. The string will be formatted like so:
"99.28099822998047,68.375 118.30699729919434,57.625 126.49999713897705,37.875 113.94499683380127,11.048999786376953 96.00499725341797,8.5"
I create the array with the following code:
public static Array StringToArray(string String)
{
var list = new List<string>();
string[] Coords = String.Split(' ', ',');
foreach (string Coord in Coords)
{
list.Add(Coord);
}
var array = list.ToArray();
return array;
}
Now my problem is; I am trying to find a way to convert it back into a string, with the same formatting. So, I could create a string simply using:
public static String ArrayToString(Array array)
{
string String = string.Join(",", array);
return String;
}
and then hopefully replace every 2nd "," with a space (" "). Is this possible? Or are there a whole other way you would do this?
Thank you in advance! I hope my question makes sense.
There is no built-in way of doing what you need. However, it's pretty trivial to achieve what it is you need e.g.
public static string[] StringToArray(string str)
{
return str.Replace(" ", ",").Split(',');
}
public static string ArrayToString(string[] array)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i <= array.Length-1; i++)
{
sb.AppendFormat(i % 2 != 0 ? "{0} " : "{0},", array[i]);
}
return sb.ToString();
}
If those are pairs of coordinates, you can start by parsing them like pairs, not like separate numbers:
public static IEnumerable<string[]> ParseCoordinates(string input)
{
return input.Split(' ').Select(vector => vector.Split(','));
}
It is easier then to reconstruct the original string:
public static string PrintCoordinates(IEnumerable<string[]> coords)
{
return String.Join(" ", coords.Select(vector => String.Join(",", vector)));
}
But if you absolutely need to have your data in a flat structure like array, it is then possible to convert it to a more structured format:
public static IEnumerable<string[]> Pairwise(string[] coords)
{
coords.Zip(coords.Skip(1), (coord1, coord2) => new[] { coord1, coord2 });
}
You then can use this method in conjunction with PrintCoordinates to reconstruct your initial string.
Here is a route to do it. I don't think other solutions were removing last comma or space. I also include a test.
public static String ArrayToString(Array array)
{
var useComma = true;
var stringBuilder = new StringBuilder();
foreach (var value in array)
{
if (useComma)
{
stringBuilder.AppendFormat("{0}{1}", value, ",");
}
else
{
stringBuilder.AppendFormat("{0}{1}", value, " ");
}
useComma = !useComma;
}
// Remove last space or comma
stringBuilder.Length = stringBuilder.Length - 1;
return stringBuilder.ToString();
}
[TestMethod]
public void ArrayToStringTest()
{
var expectedStringValue =
"99.28099822998047,68.375 118.30699729919434,57.625 126.49999713897705,37.875 113.94499683380127,11.048999786376953 96.00499725341797,8.5";
var array = new[]
{
"99.28099822998047",
"68.375",
"118.30699729919434",
"57.625",
"126.49999713897705",
"37.875",
"113.94499683380127",
"11.048999786376953",
"96.00499725341797",
"8.5",
};
var actualStringValue = ArrayToString(array);
Assert.AreEqual(expectedStringValue, actualStringValue);
}
Another way of doing it:
string inputString = "1.11,11.3 2.22,12.4 2.55,12.8";
List<string[]> splitted = inputString.Split(' ').Select(a => a.Split(',')).ToList();
string joined = string.Join(" ", splitted.Select(a => string.Join(",",a)).ToArray());
"splitted" list will look like this:
1.11 11.3
2.22 12.4
2.55 12.8
"joined" string is the same as "inputString"
Here's another approach to this problem.
public static string ArrayToString(string[] array)
{
Debug.Assert(array.Length % 2 == 0, "Array is not dividable by two.");
// Group all coordinates as pairs of two.
int index = 0;
var coordinates = from item in array
group item by index++ / 2
into pair
select pair;
// Format each coordinate pair with a comma.
var formattedCoordinates = coordinates.Select(i => string.Join(",", i));
// Now concatinate all the pairs with a space.
return string.Join(" ", formattedCoordinates);
}
And a simple demonstration:
public static void A_Simple_Test()
{
string expected = "1,2 3,4";
string[] array = new string[] { "1", "2", "3", "4" };
Debug.Assert(expected == ArrayToString(array));
}

Split it into an array

I have this string of proxy addresses, they are separated by an space, however x400 and x500 handles spaces into their addresses. What's the best approach to split it.
e.g.
smtp:john#a-mygot.com smtp:john#b-mygot.com smtp:john#c-mygot.com X400:C=us;A= ;P=mygot;O=Exchange;S=John;G=Gleen; SMTP:john#mygot.com
Expected result:
smtp:john#a-mygot.com
smtp:john#b-mygot.com
smtp:john#c-mygot.com
X400:C=us;A= ;P=mygot;O=Exchange;S=John;G=Gleen;
SMTP:john#mygot.com
thanks,
EDIT,
string mylist = "smtp:john#a-mygot.com smtp:john#b-mygot.com smtp:john#c-mygot.com X400:C=us;A= ;P=mygot;O=Exchange;S=John;G=Gleen; SMTP:john#mygot.com X500:/o=Example/ou=USA/cn=Recipients of /cn=juser smtp:myaddress";
string[] results = Regex.Split(mylist, #" +(?=\w+:)");
foreach (string part in results)
{
Console.WriteLine(part);
}
Result
smtp:john#a-mygot.com
smtp:john#b-mygot.com
smtp:john#c-mygot.com
X400:C=us;A= ;P=mygot;O=Exchange;S=John;G=Gleen;
SMTP:john#mygot.com
X500:/o=Example/ou=USA/cn=Recipients of /cn=juser
smtp:myaddress
Here is a Regex that should match the spaces before protocols. Try plugging it into Regex.Split like so:
string[] results = Regex.Split(input, #" +(?=\w+:)");
int index = smtp.indexOf("X400") ;
string[] smtps = smtpString.SubString(0,index).Split(" ") ;
int secondIndex = smtpString.indexOf("SMTP");
string xfour = smtpString.substring(index,secondIndex);
string lastString = smtpString.indexOf(secondIndex) ;
Should work, if the string format is that way.. and if I didn't screw up the indexes.. although you might want to check if the index isn't -1
Try this:
public static string[] SplitProxy(string text)
{
var list = new List<string>();
var tokens = text.Split(new char[] { ' ' });
var currentToken = new StringBuilder();
foreach (var token in tokens)
{
if (token.ToLower().Substring(0, 4) == "smtp")
{
if (currentToken.Length > 0)
{
list.Add(currentToken.ToString());
currentToken.Clear();
}
list.Add(token);
}
else
{
currentToken.Append(token);
}
}
if (currentToken.Length > 0)
list.Add(currentToken.ToString());
return list.ToArray();
}
It splits the string by spaces into tokens then goes through them one by one. If the token starts with smtp it is added to the result array. If not, that token is concatted with the following tokens to create one entry than is added to the result array. Should work with anything that has spaces and doesn't start with smtp.
I reckon the following line should do the work
var addrlist = variable.Split(new char[] { ' ' },StringSplitOptions.RemoveEmptyEntries);

C# easy way to convert a split string into columns

This is a rough one to explain. What I have is a string,
string startString = "Operations\t325\t65\t0\t10\t400"
string[] splitStart = startString.Split('\t');
I need to turn this into
Operations|325
Operations|65
Operations|0
Operations|10
Operations|400
The problem is i need this so be dynamic to if it has 10 splits I need it to do the same process 10 times, if it has 4, then it needs to do 4.
Any help would be awesome.
Sorry for any confusion, Operations is just this string, so it's not static. It really need to be [0] of the string split.
Something like:
string startString = "Operations\t325\t65\t0\t10\t400"
string[] splitStart = startString.Split('\t');
List<string> result = new List<string>();
if(splitStart.Length > 1)
for(int i = 1; i < splitStart.Length; i++)
{
result.Add(splitStart[0] + "|" + splitStart[i]);
}
If it is the strings you want, a little Linq should be fine:
string startString = "Operations\t325\t65\t0\t10\t400";
var operations = startString.Split('\t').Select(str => "Operations|" + str);
How about this?
var reFormatted = new List<string>();
foreach (var roughOne in toExplain)
{
// example of roughOne "Operations\t325\t65\t0\t10\t400"
var segments = roughOne.Split("\t");
var firstSegment = segments.First();
var sb = new StringBuilder();
foreach (var otherSegment in segments.Skip(1))
{
sb.Append(firstSegment);
sb.Append("|")
sb.Append(otherSegment);
sb.Append("\r\n");
}
reFormatted.Add(sb.ToString());
}

Extracting variable number of token pairs from a string to a pair of arrays

Here is the requirement.
I have a string with multiple entries of a particular format. Example below
string SourceString = "<parameter1(value1)><parameter2(value2)><parameter3(value3)>";
I want to get the ouput as below
string[] parameters = {"parameter1","parameter2","parameter3"};
string[] values = {"value1","value2","value3"};
The above string is just an example with 3 pairs of parameter values. The string may have 40, 52, 75 - any number of entries (less than 100 in one string).
Like this I have multiple strings in an array. I want to do this operation for all the strings in the array.
Could any one please advice how to achieve this? I'm a novice in c#.
Is using regex a better solution or is there any other method?
Any help is much appreciated.
If you didn't like RegEx's you could do something like this:
class Program
{
static void Main()
{
string input = "<parameter1(value1)>< parameter2(value2)>";
string[] Items = input.Replace("<", "").Split('>');
List<string> parameters = new List<string>();
List<string> values = new List<string>();
foreach (var item in Items)
{
if (item != "")
{
KeyValuePair<string, string> kvp = GetInnerItem(item);
parameters.Add(kvp.Key);
values.Add(kvp.Value);
}
}
// if you really wanted your results in arrays
//
string[] parametersArray = parameters.ToArray();
string[] valuesArray = values.ToArray();
}
public static KeyValuePair<string, string> GetInnerItem(string item)
{
//expects parameter1(value1)
string[] s = item.Replace(")", "").Split('(');
return new KeyValuePair<string, string>(s[0].Trim(), s[1].Trim());
}
}
It might be a wee bit quicker than the RegEx method but certainly not as flexible.
You could use RegEx class in combination with an expression to parse the string and generate these arrays by looping through MatchCollections.
http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.aspx
This does it:
string[] parameters = null;
string[] values = null;
// string SourceString = "<parameter1(value1)><parameter2(value2)><parameter3(value3)>";
string SourceString = #"<QUEUE(C2.BRH.ARB_INVPUSH01)><CHANNEL(C2.MONITORING_CHANNEL)><QMGR(C2.MASTER_NA‌​ME.TRACKER)>";
// string regExpression = #"<([^\(]+)[\(]([\w]+)";
string regExpression = #"<([^\(]+)[\(]([^\)]+)";
Regex r = new Regex(regExpression);
MatchCollection collection = r.Matches(SourceString);
parameters = new string[collection.Count];
values = new string[collection.Count];
for (int i = 0; i < collection.Count; i++)
{
Match m = collection[i];
parameters[i] = m.Groups[1].Value;
values[i] = m.Groups[2].Value;
}

Categories