Ordering a string with numbers in ascending order - c#

I currently have a string that looks like this:
string numbers = "55;9;20;3";
How would i make the numbers in ascending order like this:
string numbers = "3;9;20;55";

You can try with a combination of String.Join, OrderBy and int.Parse like the following:
numbers= String.Join(";",
numbers.Split(';').OrderBy(x=> int.Parse(x)));
You can check this working example as well

You can use System.Linq namespace for this:
using System.Linq;
...
string numbers = "55;9;20;3";
string output = String.Join(",", numbers.Split(';').Select(x => int.Parse(x)).OrderBy(x => x));

I'd break this into a four step process.
// 1) Split the numbers apart using based on the delimiting character ';'
var splitString = numbers.Split(';');
// 2) Convert the array of `string` to an array of `int`
var numberArray = splitString.Select(x => int.Parse(x));
// 3) Order the array which has been output by the `Split` method.
var orderedArray = numberArray.OrderBy(x => x);
// 4) Join the string back together again in the correct order, delimited by ';'
var orderedNumbers = string.Join(";", orderedArray);
This could be squashed together into less lines of code, but by doing it in multiple stages it should give you a good understanding of what is happening.
For example, Here is the same logic in one line of code:
string orderedNumers = string.Join(";", numbers.Split(';').OrderBy(x => int.Parse(x)));

Related

Find common characters from group of string

Given the set of below strings
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
In above strings only lower case letter "r" is common in all of them.
I know we can use Intersectto find common things in 2 string but how to do using 3 strings?
This code below i did for 2 strings
var commonString = firstPartOfstring
.Intersect(secondPartOfString)
.Select(x => x)
.FirstOrDefault()
.ToString();
But cant find how to do for 3 strings
In general case you can query the strings (lines) with a help of Linq Aggregate. Please, note, that to get string from enumeration (IEnumerable<char>) we should use Concat(), not ToString():
using System.Linq;
...
// Organize the strings into a collection, say, an array
// (Set, List etc. will do as well)
string[] lines = {
"vJrwpWtwJgWrhcsFMMfFFhFp",
"jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL",
"PmmdzqPrVvPwwTWBwg",
};
...
// Query the collection above with a help of Linq:
// We turn each string into enumeration (IEnumerable<char>)
// Aggregate all enumerations into one with a help of Intersect
// Concat characters of the final enumeration to the string
string commonString = string.Concat(lines
.Select(line => line.AsEnumerable()) // we deal with IEnumerable<char>, not string
.Aggregate((s, a) => s.Intersect(a))
.OrderBy(c => c) // In case you want common characters being ordered
);
if null can appear among the strings, change .Select(...) into
.Select(line => line?.AsEnumerable() ?? Array.Empty<char>())
Please, fiddle youself.
If you want just to intersect three strings you can do it as follow:
string first = "vJrwpWtwJgWrhcsFMMfFFhFp";
string second = "jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL";
string third = "PmmdzqPrVvPwwTWBwg";
string commonString = string.Concat(first
.Intersect(second)
.Intersect(third));
Intersect is transitive -- that means you can string them together in sequence.
var commonString = firstPartOfstring
.Intersect(secondPartOfString)
.Intersect(thirdPartOfString)
.Select(x => x).FirstOrDefault().ToString();
(nb - you can sequence them in any order - the other attribute of transitive)

find repeated substring in a string

I have a substring
string subString = "ABC";
Every time all three chars appears in a input, you get one point
for example, if input is:
"AABKM" = 0 points
"AAKLMBDC" = 1 point
"ABCC" = 1 point because all three occurs once
"AAZBBCC" = 2 points because ABC is repeated twice;
etc..
The only solution I could come up with is
Regex.Matches(input, "[ABC]").Count
But does not give me what I'm looking for.
Thanks
You could use a ternary operation, where first we determine that all the characters are present in the string (else we return 0), and then select only those characters, group by each character, and return the minimum count from the groups:
For example:
string subString = "ABC";
var inputStrings = new[] {"AABKM", "AAKLMBDC", "ABCC", "AAZBBCC"};
foreach (var input in inputStrings)
{
var result = subString.All(input.Contains)
? input
.Where(subString.Contains)
.GroupBy(c => c)
.Min(g => g.Count())
: 0;
Console.WriteLine($"{input}: {result}");
}
Output
It could be done with a single line, using Linq. However I am not very confident that this could be a good solution
string subString = "ABC";
string input = "AAZBBBCCC";
var arr = input.ToCharArray()
.Where(x => subString.Contains(x))
.GroupBy(x => x)
.OrderBy(a => a.Count())
.First()
.Count();
The result is 2 because the letter A is present only two times.
Let's try to explain the linq expression.
First transform the input string in a sequence of chars, then take only the chars that are contained in the substring. Now group these chars and order them according the the number of occurrences. At this point take the first group and read the count of chars in that group.
Let's see if someone has a better solution.
try this code :
string subString = "ABC";
var input = new[] { "AABKM", "AAKLMBDC", "ABCC", "AAZBBCC" };
foreach (var item in input)
{
List<int> a = new List<int>();
for (int i = 0; i < subString.Length; i++)
{
a.Add(Regex.Matches(item, subString.ToList()[i].ToString()).Count);
}
Console.WriteLine($"{item} : {a.Min()}");
}

How do I get quoted fields from a delimited string as a list of unquoted values using LINQ?

Original text line is:
"125"|"Bio Methyl"|"99991"|"OPT12"|"CB"|"1"|"12"|"5"|"23"
Expected string list is free of double quotes and split by |:
125
Bio Methyl
99991
The text may contain empty quoted strings as in (former "OPT12" value now empty ""):
"125"|"Bio Methyl"|"99991"|""|"CB"|"1"|"12"|"5"|"23"
So I checked these two questions & answers :QA1 and QA2 to derive my solution.
var eList = uEList.ElementAt(i).Split(BarDelimiter);
var xList = eList.ElementAt(0).Where(char.IsDigit).ToList();
Of course it doesn't work the way I need it to be since xList is a list with elements like this: xList(0) = 1, xList(1) = 2, xList(2) = 5
I do not want to write another line to join them because this doesn't look like a suitable solution. There has to be something better with LINQ right?
How about this:
// Based on OPs comment: preserve empty non-quoted entries.
var splitOptions = StringSplitOptions.None;
//change to the below if empty entries should be removed
//var splitOptions = StringSplitOptions.None;
var line = "\"125\"|\"Bio Methyl\"|\"99991\"|\"OPT12\"|\"CB\"|\"1\"|\"12\"|\"5\"|\"23\"";
var result = line
.Split(new[] { "|" }, splitOptions)
.Select(p => p.Trim('\"'))
.ToList();
Console.WriteLine(string.Join(", ", result));
The Split(...) statement splits the input into an array with parts like
{ \"99991\", \"OPT12\", ... };
The p.Trim('\"') statement removes the leading and trailing quote from each of the parts.
As an alternative to the trimming, if there's no " in your values, you could simply sanitize the input before splitting it. You can do so by replacing the " symbol by nothing (either "" or string.Empty).
Your Split code would then give the correct result afterwards:
string uEList = "\"125\"|\"Bio Methyl\"|\"99991\"|\"OPT12\"|\"CB\"|\"1\"|\"12\"|\"5\"|\"23\"";
var eList = uEList.Replace("\"", string.Empty).Split(BarDelimiter);

Shortcut for splitting only once in C#?

Okay, lets say I have a string:
string text = "one|two|three";
If I do string[] texts = text.Split('|'); I will end up with a string array of three objects. However, this isn't what I want. What I actually want is to split the string only once... so the two arrays I could would be this:
one
two|three
Additionally, is there a way to do a single split with the last occurrence in a string? So I get:
one|two
three
As well, is there a way to split by a string, instead of a character? So I could do Split("||")
Split method takes a count as parameter, you can pass 2 in that position, which basically says that you're interested in only 2 elements maximum. You'll get the expected result.
For second question: There is no built in way AFAIK. You may need to implement it yourself by splitting all and joining first and second back.
C#'s String.Split() can take a second argument that can define the number of elements to return:
string[] texts = text.Split(new char[] { '|' }, 2);
For your first scenario, you can pass a parameter of how many strings to split into.
var text = "one|two|three";
var result = text.Split(new char[] { '|' }, 2);
Your second scenario requires a little more magic.
var text = "one|two|three";
var list = text.Split('|');
var result = new string[] { string.Join("|", list, 0, list.Length - 1), list[list.Length - 1] };
Code has not been verified to check results before using.
Well, I took it as a challenge to do your second one in one line. The result is... not pretty, mostly because it's surprisingly difficult to reverse a string and keep it as a string.
string text = "one|two|three";
var result = new String(text.Reverse().ToArray()).Split(new char[] {'|'}, 2).Reverse().Select(c => new String(c.Reverse().ToArray()));
Basically, you reverse it, then follow the same procedure as the first one, then reverse each individual one, as well as the resulting array.
You can simply do like this as well...
//To split at first occurence of '|'
if(text.Containts('|')){
beginning = text.subString(0,text.IndexOf('|'));
ending = text.subString(text.IndexOf('|');
}
//To split at last occurence of '|'
if(text.Contains('|')){
beginning = text.subString(0,text.LastIndexOf('|'));
ending = text.subString(text.LastIndexOf('|');
}
Second question was fun. I solved it this way:
string text = "one|two|three";
var result =
new []
{
string.Concat(text.ToCharArray().TakeWhile((c, i) => i <= text.LastIndexOf("|"))),
string.Concat(text.ToCharArray().SkipWhile((c, i) => i <= text.LastIndexOf("|")))
};

Split string that contains array to get array of values C#

I have a string that contains an array
string str = "array[0]=[1,a,3,4,asdf54,6];array[1]=[1aaa,2,4,k=6,2,8];array[2]=[...]";
I'd like to split it to get an array like this:
str[0] = "[1,a,3,4,asdf54,6]";
str[1] = "[1aaa,2,4,k=6,2,8]";
str[2] = ....
I've tried to use Regex.Split(str, #"\[\D+\]") but it didn't work..
Any suggestions?
Thanks
SOLUTION:
After seen your answers I used
var arr = Regex.Split(str, #"\];array\[[\d, -]+\]=\[");
This works just fine, thanks all!
var t = str.Split(';').Select(s => s.Split(new char[]{'='}, 2)).Select(s => s.Last()).ToArray();
In regex, \d matches any digit, whilst \D matches anything that is not a digit. I assume your use of the latter is erroneous. Additionally, you should allow your regex to also match negation signs, commas, and spaces, using the character class [\d\-, ]. You can also include a lookahead lookbehind for the = character, written as (?<=\=), in order to avoid getting the [0], [1], [2], ...
string str = "array[0]=[1,2,3,4,5,6];array[1]=[1,2,4,6,2,8];array[2]=[...]";
string[] results = Regex.Matches(str, #"(?<=\=)\[[\d\-, ]+\]")
.Cast<Match>()
.Select(m => m.Value)
.ToArray();
Try this - using regular expression look behind to grab the relevant parts of your string.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace RegexSplit
{
class Program
{
static void Main(string[] args)
{
string str = "array[0]=[1,2,3,4,5,6];array[1]=[1,2,4,6,2,8];array[2]=[...]";
Regex r = new Regex(#"(?<=\]=)(\[.+?\])");
string[] results = r.Matches(str).Cast<Match>().Select(p => p.Groups[1].Value).ToArray();
}
}
}
BONUS - convert to int[][] if you are fancy.
int[][] ints = results.Select(p => p.Split(new [] {'[', ',', ']'}, StringSplitOptions.RemoveEmptyEntries)
.Where(s => { int temp; return int.TryParse(s, out temp);}) //omits the '...' match from your sample. potentially you could change the regex pattern to only catch digits but that isnt what you wanted (i dont think)
.Select(s => int.Parse(s)).ToArray()).ToArray();
Regex would be an option, but it would be a bit complicated. Assuming you don't have a parser for your input, you can try the following:
-Split the string by ; characters, and you'd get a string array (e.g. string[]):
"array[0]=[1,2,3,4,5,6]", "array[1]=[1,2,4,6,2,8]", "array[2]=[...]". Let's call it list.
Then for each of the elements in that array (assuming the input is in order), do this:
-Find the index of ]=, let that be x.
-Take the substring of your whole string from the starting index x + 2. Let's call it sub.
-Assign the result string as the current string in your array, e.g. if you are iterating with a regular for loop, and your indexing variable is i such as for(int i = 0; i < len; i++){...}:
list[i] = sub.
I know it is a dirty and an error-prone solution, e.g. if input is array[0] =[1,2... instead of array[0]=[1,2,... it won't work due to the extra space there, but if your input mathces that exact pattern (no extra spaces, no newlines etc), it will do the job.
UPDATE: cosset's answer seems to be the most practical and easiest way to achieve your result, especially if you are familiar with LINQ.
string[] output=Regex.Matches(input,#"(?<!array)\[.*?\]")
.Cast<Match>()
.Select(x=>x.Value)
.ToArray();
OR
string[] output=Regex.Split(input,#";?array[\d+]=");
string str = "array[0]=[1,a,3,4,asdf54,6];array[1]=[1aaa,2,4,k=6,2,8];array[2]=[2,3,2,3,2,3=3k3k]";
string[] m1 = str.Split(';');
List<string> m3 = new List<string>();
foreach (string ms in m1)
{
string[] m2 = ms.Split('=');
m3.Add(m2[1]);
}

Categories

Resources