Split and append a string? - c#

Right now I take in a string like this "112233 112233 112233 112233", and I split it into an array like this:
string text = ProcessString("112233 112233");
string[] dates = text.Split(' ');
And that works great, but I want to use string builder to build my string so they would end up like 11-22-33 11-22-33 etc.
So I did try this:
static string ProcessString(string input)
{
StringBuilder buffer = new StringBuilder(input.Length * 3 / 2);
for (int i = 0; i < input.Length; i++)
{
if ((i > 0) & (i % 2 == 0))
buffer.Append("-");
buffer.Append(input[i]);
}
return buffer.ToString();
}
It works, but it does not match the expected output of:
11-22-33
11-22-33
My current output is:
11-22-33-
1-12-23-3
-11-22-33
What can I do to fix this?

You can process a single string simply by iterating and collecting size-2 substrings of the string, and then joining them by the - character:
string s = "112233";
List<string> parts = new List<string>(s.Length / 2);
for (int i = 0; i < s.Length; i += 2)
parts.Add(s.Substring(i, 2));
Console.WriteLine(string.Join("-", parts)); // 11-22-33
So, for your full problem, you could do this:
static string ProcessString(string input)
{
var segments = input.Split(' ').Select(s =>
{
List<string> parts = new List<string>(s.Length / 2);
for (int i = 0; i < s.Length; i += 2)
parts.Add(s.Substring(i, 2));
return string.Join("-", parts);
});
return string.Join(" ", segments);
}

How about regex:
string s = "112233";
string pattern = #"\d{2}\B";
string result = Regex.Replace(s, pattern, m => m.Value + "-");

Can i offer you another Regex + LINQ approach?
var newDates = dates.Select(d => Regex.Replace(d, ".{2}", "$0-").Trim('-'));
string result = string.Join(" ", newDates);
But i like this extension more because it's readable and re-usable:
public static IEnumerable<String> SplitInParts(this String s, Int32 partLength)
{
if (s == null)
throw new ArgumentNullException("s");
if (partLength <= 0)
throw new ArgumentException("Part length has to be positive.", "partLength");
for (var i = 0; i < s.Length; i += partLength)
yield return s.Substring(i, Math.Min(partLength, s.Length - i));
}
Then the code is even easier:
var newDates = dates.Select(d => string.Join("-", d.SplitInParts(2)));
string result = string.Join(" ", newDates);

I have this approach :
string input = "112233 445566 778899 101010";
string[] dates = input.Split(' ');
foreach (string date in dates){
Console.WriteLine(date);
string result = date.Substring(0, 2) + '-' + date.Substring(2, 2) + "-" + date.Substring(4, 2);
Console.WriteLine(result);
}

You can use Array.ConvertAll:
string str = "112233 112233 112233 112233";
string[] dates = str.Split();
dates = Array.ConvertAll(dates, s => s.Insert(4, "-").Insert(2, "-"));
foreach (var s in dates)
Console.WriteLine(s);

Related

How to rearrange a string so no adjent letters are the same

I am trying to rearrange a given string, so no two adjacent letters are the same.
For that I'm thinking to count every distinct letter's occurence, and then rearrange the string the characters occurence number
example:
Input: AABAABBC
Output: AAAABBBC
and after that spliting it in 2 different strings
AAAA BBBC
and then trying to get the final result.
My question is how do I rearrange the string without using Linq?
Here is my code so far:
private static string GetDistinctChars(string text)
{
string result = "";
foreach (char c in text)
{
if (!result.Contains(c))
{
result += c;
}
}
return result;
}
private static double GetCharOccurrence(string text, char charToCount)
{
int count = 0;
foreach (char c in text)
{
if (c == charToCount)
{
count++;
}
}
return count;
}
You can do it like that:
string example = "AABBAACDCAA";
var orderList = example.OrderBy(x => x).ToList();
List<string> letters = new List<string>();
string temp = string.Empty;
for(int i = 0; i < orderList.Count; i++)
{
temp += orderList[i];
if (i + 1 == orderList.Count)
{
letters.Add(temp);
break;
}
if(orderList[i] != orderList[i + 1])
{
letters.Add(temp);
temp = string.Empty;
}
}
string result = String.Join(" ", letters);
Console.WriteLine(result);
If you don't want to use Linq Order by method, you should implement sorting algorithm like this:
static char[] SortArray(char[] array)
{
int length = array.Length;
char temp = array[0];
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length; j++)
{
if (array[i] > array[j])
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
return array;
}
and use it in your program:
string example = "AABBAACDCAA";
var orderList = SortArray(example.ToCharArray());
List<string> letters = new List<string>();
string temp = string.Empty;
for(int i = 0; i < orderList.Length; i++)
{
temp += orderList[i];
if (i + 1 == orderList.Length)
{
letters.Add(temp);
break;
}
if(orderList[i] != orderList[i + 1])
{
letters.Add(temp);
temp = string.Empty;
}
}
string result = String.Join(" ", letters);
Console.WriteLine(result);
alternativly, if you don't want to use list anymore, you can operate only on strigns:
string example = "AABBAACDCAA";
var orderList = SortArray(example.ToCharArray());
string lettersString = string.Empty;
for (int i = 0; i < orderList.Length; i++)
{
lettersString += orderList[i];
if (i + 1 == orderList.Length)
break;
if (orderList[i] != orderList[i + 1])
lettersString += " ";
}
Console.WriteLine(lettersString);
You can find your problem on LeetCode, it's a problem #767.
My algorithm is
If we have too many of same characters, we can't solve the problem (e.g. "aaaaaabc")
If solution exists, we can sort characters aababc -> aaabbc and then take item by item from the beginning and from the center:
For instance:
aababc -> aaabbc (ordered by frequency: a appears 3 time, b - 2, c - 1)
then
aaabbc => ab
^ ^
take these
aaabbc => abab
^ ^
take these
aaabbc => ababac <- final answer
^ ^
take these
Code:
using System.Linq;
using System.Text;
...
public static string ReorganizeString(string s) {
int count = s.GroupBy(c => c).Max(g => g.Count());
// One of the item is too frequent, no solutions
if (count > (s.Length + 1) / 2)
return "";
string st = string.Concat(s
.GroupBy(c => c)
.OrderByDescending(g => g.Count())
.ThenBy(g => g.Key) // not required, just for aesthetic
.SelectMany(c => c));
StringBuilder sb = new StringBuilder(s.Length);
for (int i = 0; i < s.Length / 2; ++i) {
sb.Append(st[i]);
sb.Append(st[(st.Length + 1) / 2 + i]);
}
// Middle character
if (s.Length % 2 != 0)
sb.Append(st[st.Length / 2]);
return sb.ToString();
}
Demo:
string value = "AABAABBC";
Console.Write(ReorganizeString(value));
Output:
ABABABAC
Fiddle it yourself.
Edit: If StringBuilder (as well as System.Text) is really forbidden, we can use string, which, however, slows down the routine:
using System.Linq;
...
public static string ReorganizeString(string s) {
int count = s.GroupBy(c => c).Max(g => g.Count());
// One of the item is too frequent, no solutions
if (count > (s.Length + 1) / 2)
return "";
string st = string.Concat(s
.GroupBy(c => c)
.OrderByDescending(g => g.Count())
.ThenBy(g => g.Key) // not required, just for aesthetic
.SelectMany(c => c));
string result = "";
for (int i = 0; i < s.Length / 2; ++i) {
result += st[i];
result += st[(st.Length + 1) / 2 + i];
}
// Middle character
if (s.Length % 2 != 0)
result += st[st.Length / 2];
return result;
}

How can I divide string into 3 parts?

I want ask something about split string. Example:
string str = "1,2,3,4,5,6,7,8,9,10";
I want to divide str into 3 parts so parts look like:
string str1 = "1,2,3";
string str2 = "4,5,6";
string str3 = "7,8,9,10";
How can I do this?
You can try this
public static string SplitString(string data,int size)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
if (i % size == 0)
sb.Append(' ');
sb.Append(data[i]);
}
return sb.ToString();
}
Try following :
int size = 3;
string str = "1,2,3,4,5,6,7,8,9,10";
string[] splitArray = str.Split(new char[] { ',' }).ToArray();
string[] results = splitArray.Select((x,i) => new { index = i, number = x})
.GroupBy(x => (x.index < size * (splitArray.Length/size)) ? (x.index / (splitArray.Length/size)) : (x.index / (splitArray.Length/size)) - 1)
.Select(x => string.Join(",", x.Select(y => y.number)))
.ToArray();

C# merge lines of strings into groups of 3 at a time

I have a string like this (including newlines)
A2,
10.22,
-57,
A,
10.23,
-68,
A2,
10.24,
-60,
LB,
10.25,
-62,
I am trying to make this string to look like this:
A2,10.22,-57,
A,10.23,-68,
A2,10.24,-60,
LB,10.25,-62,
I need to join string in every 3 line i have tried :
int numLines = a.Split('\n').Length;
for (int i = 0; i < numLines; i += 3)
{
richTextBox1.Text = a.Replace("\n", "");
}
But it is not working for me. Please help me out
You can also approach this with LINQ, by using the index overload of .Select to retain a running count of the line numbers, and then to group them into groups of 3 - I've used integer division to Floor the line index, 3 at a time, but there are likely other suitable ways.
var groups = values.Select((s, idx) => (Index: idx / 3, Value: s))
.GroupBy(x => x.Index);
Where each item in the groups above will be IEnumerable<(Index, Value)>.
You'll also need to be wary of newlines - these may be \r\n in Windows, not just the \n you've indicated.
Here's an example:
var a =
#"A2,
10.22,
-57,
A,
10.23,
-68,
A2,
10.24,
-60,
LB,
10.25,
-62,";
var values = a.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
var groups = values.Select((s, idx) => (Index: idx / 3, Value: s))
.GroupBy(x => x.Index);
foreach (var grp in groups)
{
Console.WriteLine(string.Join("", grp.Select(x => x.Value)));
}
Since you've already got commas at the end of each string (including the last one), there's no need to add another separator.
Output:
A2,10.22,-57,
A,10.23,-68,
A2,10.24,-60,
LB,10.25,-62,
Why not use the array that the split gives you instead?
var newArr = a.Split('\n');
for (int i = 0; i < newArr.Length; i += 3)
{
richTextBox1.Text = newArr[i] + newArr[i + 1] + newArr[i + 2];
}
Just don't forget to check the length of the arrays so that you don't get a IndexOutOfRange Exception.
I'm assuming that the input is actually coming from a file here.
var file = //file path
var sb = new StringBuilder();
var lineNum = 1;
var output = string.Empty;
using (var reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (lineNum % 3 == 0)
{
output += sb.ToString() + "\n";
sb.Clear();
}
else
sb.Append(line);
lineNum++;
}
}
richTextBox1.Text = output;
Try this solution which is a combination of linq and for loop
var result = "";
var items = yourInputString.Split('\n');
for(var i=0; i<items.Count();i=i+3)
{
result += string.Join(",",items.Skip(i).Take(3))+"\n";
}
static void Main(string[] args)
{
var Lines = System.IO.File.ReadAllLines("input.txt");
var Result = new StringBuilder();
var SB = new StringBuilder();
for (var i = 0; i < Lines.Length; i++)
{
SB.Append(Lines[i]);
if ((i+1) % 3 == 0)
{
Result.Append($"{SB.ToString()}{Environment.NewLine}");
SB.Clear();
}
}
System.IO.File.WriteAllText("output.txt", Result.ToString());
}
Try to use Aggregate function
var outPutList = data.Replace("\r", string.Empty).Replace("\n", string.Empty).Split(",").Aggregate(new StringBuilder(""), (x, y) =>
{
if (double.TryParse(y, out double parsedValue))
x.Append(" " + parsedValue);
else
{
x.Append(Environment.NewLine);
x.Append(y.Trim());
}
return x;
});
richTextBox1.Text = outPutList.ToString();
Here is the output
try this works
private void button1_Click(object sender, EventArgs e)
{
//put your string in a textxbox with multiline property set to true
string[] s = textBox1.Text.Replace("\r", "").Replace("\n", "").Split(',');
string r = "";
for (int i = 0; i < s.Length; i++)
{
r = r + s[i] + ",";
if ((i + 1) % 3 == 0)
r = r + "+";
}
if (r.Substring(r.Length - 1, 1) == ",")
r = r.Substring(0, r.Length - 1);
if (r.Substring(r.Length - 1, 1) == "+")
r = r.Substring(0, r.Length - 1);
string[] finalArrayString = r.Trim().Split('+');
//just for show the result
textBox1.Text = "";
for (int i = 0; i < finalArrayString.Length; i++)
textBox1.Text = textBox1.Text + finalArrayString[i] + "\r\n";
}
hope it helps you

c# finding characters between brackets

I can't get it to work,
I need to get a character ex : i [L]ove [B]asketball and [H]ockey
i would like to take the L, B and H out of this string and show them in a console writeline
without using regex
I though about finding the position of [ with an indexof and add + 1 to get the letter and then replace the [ with something else ex: [ into &
so i could do a foreach bracket in that string... but i don't think it'll work o.O
Console.WriteLine("Characters are : ");
foreach(Brackets in sentence)..
string str = " i [L]ove [B]asketball and [H]ockey";
string[] array = str.Split('[');
foreach (var item in array)
{
if(item.Contains(']'))
Console.WriteLine(item[0]);
}
and you will get:
L
B
H
This would work as long as you don't have unpaired square brackets and there is a character between those square brackets.
You can do this without the split:
string str = " i [L]ove [B]asketball and [H]ockey";
for (int i = 0; i < str.Length; i++)
{
if(str[i] == '[')
Console.WriteLine(str[1 + i++]);
}
Using LINQ:
string s = "i [L]ove [B]asketball and [H]ockey";
var chars = s.Where((c, i) => i > 0 && s[i - 1] == '[' &&
i < s.Length - 1 && s[i + 1] == ']');
Equivalently:
var chars = Enumerable.Range(1, s.Length - 2)
.Where(i => s[i - 1] == '[' && s[i + 1] == ']')
.Select(i => s[i]);
You can use this regex to get the values between the brakets:
string input = "I [L]ove [B]asketball and [H]ockey";
var regex = new Regex(#"\[.*?\]");
var matches = regex.Matches(input);
foreach (var match in matches)
{
var letter = Regex.Replace(match.ToString(), #"\[|\]", string.Empty);
Console.WriteLine(letter);
}
With regex:
string str = " i [L]ove [B]asketball and [H]ockey";
Match match = Regex.Match(str, #"\[(.*?)\]");
StringBuilder sb = new StringBuilder();
//iterate over all matches
do
{
sb.Append(match);
match = match.NextMatch();
}while(match.Success); //condition
//note: Dump() only works in linqpad. Use Console.WriteLine() instead
sb.Dump();
//without brackets:
sb.ToString().Split(new []{'[',']'}, StringSplitOptions.RemoveEmptyEntries).Dump();
I have come up with lengthy code but it works with all the cases
Try This:
static void Main()
{
string line = "i [L]ove [B]asketball and [H]ockey";
int count = 0;
char temp=' ';
string str="";
foreach (char ch in line)
{
if (ch == '[')
{
count++;
}
else if (count ==1)
{
count++;
temp=ch;
}
else if(count==2 && ch==']')
{
str+=temp;
count=0;
}
else
{
count = 0;
}
}
Console.WriteLine(str);
}

split string around newline after some interval

I am trying to make some logic, but it is not ful proof yet:
string s = "1234567877y";
StringBuilder sb = new StringBuilder(s);
for (int i = 5; i <= s.Length + (s.Length / 5 ); i += 5 + (s.Length / 5) )
{
sb.Insert(i, Environment.NewLine);
}
Console.WriteLine(sb.ToString());
Console.ReadKey();
Output should be:
12345
67877
y
StringBuilder contain: "12345\r\n67877\r\ny"
But if i change input string i am not getting desired result. What i can do here or suggest some other way around.
EDIT:
if i change
string s = "1234567877y3434";
output will be
12345
67877y
3434
Another concise approach is using GroupBy:
string s = "1234567877y";
IEnumerable<string> groups = s.Select((c, index) => new{ c, index })
.GroupBy(x => x.index / 5)
.Select(xg => string.Join("", xg.Select(x => x.c)));
string result = string.Join(Environment.NewLine, groups);
Here is an approach with a StringBuilder which is more efficient:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
if ((i+1) % 5 == 0)
sb.Append(s[i]).Append(Environment.NewLine);
else
sb.Append(s[i]);
}
i would do it this way :)
string s = "1234567877y3434";
for (int i = 5; i < s.Length; i += 5 + Environment.NewLine.Length)
{
s = s.Substring(0, i) + Environment.NewLine + s.Substring(i, s.Length - i);
}
EDIT: i corrected my code using the suggstestion from Chris using Environment.NewLine instead of \r\n

Categories

Resources