I would like to split a string deliminated by a character such as ‘&’, but in the case where some values contain the deliminator I would like to escape with double quotes. What is an elegant approach to splitting while ignoring the deliminating characters that have been escaped while also accounting for escape character escapes?
For example split this string properly
var1=asdfasdf&var2=contain””quote&var3=”contain&delim”&var4=”contain””both&”
Into:
var1=asdfasdf
var2=contain"quote
var3=contain&delim
var4=contain"both&
Incidentally, I am thinking Regex...
My solution, with test:
void TestCharlesParse()
{
string s = #"var1=asdfasdf&var2=contain""""quote&var3=""contain&delim""&var4=""contain""""both&""";
string[] os = CharlesParse(s);
for (int i = 0; i < os.Length; i++)
System.Windows.Forms.MessageBox.Show(os[i]);
}
string[] CharlesParse(string inputString)
{
string[] escapedQuotes = { "\"\"" };
string[] sep1 = inputString.Split(escapedQuotes, StringSplitOptions.None);
bool quoted = false;
ArrayList sep2 = new ArrayList();
for (int i = 0; i < sep1.Length; i++)
{
string[] sep3 = ((string)sep1[i]).Split('"');
for (int j = 0; j < sep3.Length; j++)
{
if (!quoted)
{
string[] sep4 = sep3[j].Split('&');
for (int k = 0; k < sep4.Length; k++)
{
if (k == 0)
{
if (sep2.Count == 0)
{
sep2.Add(sep4[k]);
}
else
{
sep2[sep2.Count - 1] = ((string)sep2[sep2.Count - 1]) + sep4[k];
}
}
else
{
sep2.Add(sep4[k]);
}
}
}
else
{
sep2[sep2.Count - 1] = ((string)sep2[sep2.Count - 1]) + sep3[j];
}
if (j < (sep3.Length-1))
quoted = !quoted;
}
if (i < (sep1.Length - 1))
sep2[sep2.Count - 1] = ((string)sep2[sep2.Count - 1]) + "\"";
}
string[] ret = new string[sep2.Count];
for (int l = 0; l < sep2.Count; l++)
ret[l] = (string)sep2[l];
return ret;
}
Related
I have to rewrite the LCS algorithm because some company policies.
I've already get done the LCS algorithm, but next step is to identify which lines were removed from the previous text and which one were added in the current text.
I tried a simple check thought the lines, but it won't work if I got a text with duplicated lines.
He is my code:
LCS Method
private static string[] LcsLineByLine(string previous, string current)
{
string[] Previous = previous.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
string[] Current = current.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
string lcsResult = string.Empty;
int a = Previous.Length;
int b = Current.Length;
int[,] table = new int[a + 1, b + 1];
//create a table with first line and column equal 0
for (int i = 0; i <= a; i++)
table[i, 0] = 0;
for (int j = 0; j <= b; j++)
table[0, j] = 0;
//create a table matrix
for (int i = 1; i <= a; i++)
{
for (int j = 1; j <= b; j++)
{
if (string.Equals(Previous[i - 1].Trim(), Current[j - 1].Trim(), StringComparison.InvariantCultureIgnoreCase))
{
table[i, j] = table[i - 1, j - 1] + 1;
}
else
{
table[i, j] = Math.Max(table[i, j - 1], table[i - 1, j]);
}
}
}
//get the lcs string array with the differences
int index = table[a, b];
string[] lcs = new string[index + 1];
lcs[index] = "0";
while (a > 0 && b > 0)
{
if (string.Equals(Previous[a - 1].Trim(), Current[b - 1].Trim(), StringComparison.InvariantCultureIgnoreCase))
{
lcs[index - 1] = Previous[a - 1].Trim();
a--;
b--;
index--;
}
else if (table[a - 1, b] > table[a, b - 1])
a--;
else
b--;
}
return lcs;
}
And this is the code that is not working with duplicated lines with same value.
Method to get all deleted items in the previous text:
private List<DiffItem> GetDiffPrevious(string[] previous, string[] diff)
{
List<DiffItem> differences = new List<DiffItem>();
//check items deleted
int line = 0;
for (int i = 0; i < previous.Length; i++)
{
bool isAbsent = false;
for (int j = 0; j < diff.Length; j++)
{
if (string.Equals(previous[i].Trim(), diff[j].Trim(), StringComparison.InvariantCultureIgnoreCase))
{
differences.Add(new DiffItem() { Position = line, Text = diff[j], Status = DiffStatus.Equal });
line++;
isAbsent = false;
break;
}
else
{
isAbsent = true;
}
}
//mark as deleted
if (isAbsent)
{
differences.Add(new DiffItem() { Position = line, Text = previous[i].Trim(), Status = DiffStatus.Deleted });
line++;
}
}
return differences;
}
If anyone could help me or any feedback would be great. Just a reminder, I cannot use third party libraries.
Thanks in advance.
I found the solution!
Basically, I rewrite the two lists and translated using Hashtable, so all the values will be unique by line. Then, I use the method LCS and got the result as expected.
I hope it helps somebody.
There is a .txt file what I have to read, compress and make an output txt for the compressed txt. Could anyone tell me what should I fix in my code?
My code:
namespace Tomorites
{
class Compression
{
public void Compress(char[,] source)
{
for (int i = 0; i < source.GetLength(0); i++)
{
int white = 0;
int red = 0;
for (int j = 0; j < source.GetLength(1); j++)
{
if (source[i, j] == 'P')
{
if (source[i, j] > 0)
{
red++;
Console.Write(red + " P ");
}
}
else if(source[i,j]=='F')
{
if (source[i, j] > 0)
{
white++;
Console.Write(white + " F ");
}
}
}
Console.WriteLine();
}
}
}
}
My console output
Source txt file
The compressed txt file which has to be
You was pretty close, but messed one important thing: reset first char counter when second char appear or second char counter when first char appear.
Also source[i, j] > 0 condition do nothing for you.
So at result we may have:
Fill source array:
static void Main(string[] args)
{
// Declare array
char[,] source = new char[7, 10];
// Fill array as at example
for (int i = 0; i < source.GetLength(0); i++)
for (int j = 0; j < source.GetLength(1); j++)
source[i, j] = i == 3 || j == 3 ? 'F' : 'P';
// Print filled array to Console
Console.WriteLine("Source:\n" + new string('-', 10));
for (int i = 0; i < source.GetLength(0); i++)
{
for (int j = 0; j < source.GetLength(1); j++)
Console.Write(source[i, j] + " ");
Console.WriteLine();
}
// Just new line
Console.WriteLine();
// Now "compress"
Console.WriteLine("Compressed:\n" + new string('-', 10));
Compress(source);
Console.ReadKey();
}
Source output:
Compress source array:
static void Compress(char[,] source)
{
// Declare counters for P and F chars
int PCount = 0, FCount = 0;
for (int i = 0; i < source.GetLength(0); i++)
{
for (int j = 0; j < source.GetLength(1); j++)
{
if (source[i, j] == 'P')
{
// If char is P - then count P's up
PCount++;
// If there was F char counted before (> 0) - print it and reset counter
if (FCount > 0)
{
Console.Write(FCount + " F ");
FCount = 0;
}
}
else if (source[i, j] == 'F')
{
// If char is P - then count F's up
FCount++;
// If there was P char counted before (> 0) - print it and reset counter
if (PCount > 0)
{
Console.Write(PCount + " P ");
PCount = 0;
}
}
}
// Before go to next "row" - print remained P or F counts and again, reset counters
if (PCount > 0)
{
Console.Write(PCount + " P ");
PCount = 0;
}
else if (FCount > 0)
{
Console.Write(FCount + " F ");
FCount = 0;
}
// Go new "row"
Console.WriteLine();
}
}
Compressed output:
UPD.
My answer is just solution for a provided example source and example output. #Dmitry Bychenko's solution is universal, not dependent on any two specific characters so in general use I recommend his way.
You can try something like this (you can fiddle with the code):
public static string Compress(char[,] source) {
if (null == source || source.GetLength(0) <= 0 || source.GetLength(1) <= 0)
return "";
StringBuilder sb = new StringBuilder();
for (int row = 0; row < source.GetLength(0); ++row) {
if (sb.Length > 0)
sb.AppendLine();
int count = 0;
char prior = '\0';
bool left = true;
for (int col = 0; col < source.GetLength(1); ++col) {
if (count == 0 || prior == source[row, col])
count += 1;
else {
if (!left)
sb.Append(' ');
left = false;
sb.Append($"{count} {prior}");
count = 1;
}
prior = source[row, col];
}
if (!left)
sb.Append(' ');
sb.Append($"{count} {prior}");
}
return sb.ToString();
}
Demo:
char[,] test = new char[,] {
{'a', 'a', 'a', 'a'},
{'a', 'b', 'c', 'c'},
};
Console.WriteLine(Compress(test));
Outcome:
4 a
1 a 1 b 2 c
input:string arabicStr = "inrr أربعة عشر anp خمسين paisle";
but my desire output is: "paisle. خمسين anp عشر أربعة inrr "
class ReverseString
{
static void Main(string[] args)
{
int i;
string Temp = string.Empty;
string Str;
Console.WriteLine("Enter string");
Str = Console.ReadLine();
int Prev = Str.Length - 1;
for (i = Str.Length - 1; i >= 0; i--)
{
if (Str[i] == ' ' || i == 0)
{
if (i == 0)
Temp += Str[i];
for (int j = i + 1; j <= Prev; j++)
{
Temp += Str[j];
}
Temp += ' ';
Prev = i - 1;
}
else
{
continue;
}
}
Console.WriteLine(Temp);
}
}
}
Just split it with Spaces, Reverse it and then again join it with Spaces:
string result = string.Join(" ", input.Split(' ').Reverse());
I trying to do sorting without use of any method or function
My Code :
string[] names = { "Flag", "Nest", "Cup", "Burg", "Yatch", "Next" };
string name = string.Empty;
Console.WriteLine("Sorted Strings : ");
for (int i = 0; i < names.Length; i++)
{
for (int j = i + 1; j < names.Length; j++)
{
for (int c = 0; c < names.Length; c++)
{
if (names[i][c] > names[j][c])
{
name = names[i];
names[i] = names[j];
names[j] = name;
}
}
}
Console.WriteLine(names[i]);
}
Please let me bring any solution for this code ?
In this code i am getting "Index was outside the bounds of the array" exception
int temp = 0;
int[] arr = new int[] { 20, 65, 98, 71, 64, 11, 2, 80, 5, 6, 100, 50, 13, 9, 80, 454 };
for (int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] > arr[j])
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
Console.WriteLine(arr[i]);
}
Console.ReadKey();
You need to implement a sorting algorithm.
A very simple algorithm you can implement is the insertion sort:
string[] names = { "Flag", "Nest", "Cup", "Burg", "Yatch", "Next" };
for (int i = 0; i < names.Length; i++)
{
var x = names[i];
var j = i;
while(j > 0 && names[j-1].CompareTo(x) > 0)
{
names[j] = names[j-1];
j = j-1;
}
names[j] = x;
}
string[] names = { "Flag", "Next", "Cup", "Burg", "Yatch", "Nest" };
string name = string.Empty;
Console.WriteLine("Sorted Strings : ");
for (int i = 0; i < names.Length; i++)
{
int c = 0;
for (int j = 1; j < names.Length; j++)
{
if (j > i)
{
Sort:
if (names[i][c] != names[j][c])
{
if (names[i][c] > names[j][c])
{
name = names[i];
names[i] = names[j];
names[j] = name;
}
}
else
{
c = c + 1;
goto Sort;
}
}
}
Console.WriteLine(names[i]);
}
I you were conflicting in length of names array and comparing string. Below is the working solution . I have tested it it's working now
static void Main(string[] args)
{
int min=0;
string[] names = { "Flag", "Nest", "Cup", "Burg", "Yatch", "Next" };
string name = string.Empty;
Console.WriteLine("Sorted Strings : ");
for (int i = 0; i < names.Length-1; i++)
{
for (int j = i + 1; j < names.Length;j++ )
{
if(names[i].Length < names[j].Length)
min =names[i].Length;
else
min =names[j].Length;
for(int k=0; k<min;k++)
{
if (names[i][k] > names[j][k])
{
name = names[i].ToString();
names[i] = names[j];
names[j] = name;
break;
}
else if(names[i][k] == names[j][k])
{
continue;
}
else
{
break;
}
}
}
}
for(int i= 0;i<names.Length;i++)
{
Console.WriteLine(names[i]);
Console.ReadLine();
}
}
}
class Program
{
static void Main(string[] args)
{
int[] arr = new int[] {9,1,6,3,7,2,4};
int temp = 0;
for (int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length;j++)
{
if(arr[i]>arr[j])
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
Console.Write(arr[i]+",");
}
Console.ReadLine();
}
for (int i = 0; i < names.Length; i++)
{
string temp = "";
for (int j = i + 1; j < names.Length; j++)
{
if (names[i].CompareTo(names[j]) > 0)
{
temp = names[j];
names[j] = names[i];
names[i] = temp;
}
}
}
public int compareing(string a, string b)
{
char[] one = a.ToLower().ToCharArray();
char[] two = b.ToLower().ToCharArray();
int ret = 0;
for (int i = 0; i < one.Length; i++)
{
for (int j = 0; j < two.Length; j++)
{
Loop:
int val = 0;
int val2 = 0;
string c = one[i].ToString();
char[] c1 = c.ToCharArray();
byte[] b1 = ASCIIEncoding.ASCII.GetBytes(c1);
string A = two[j].ToString();
char[] a1 = A.ToCharArray();
byte[] d1 = ASCIIEncoding.ASCII.GetBytes(a1);
int sec = d1[0];
int fir = b1[0];
if (fir > sec)
{
return ret = 1;
break;
}
else
{
if (fir == sec)
{
j = j + 1;
i = i + 1;
if (one.Length == i)
{
return ret = 0;
}
goto Loop;
}
else
{
return 0;
}
}
}
}
return ret;
}
public void stringcomparision(List<string> li)
{
string temp = "";
for(int i=0;i<li.Count;i++)
{
for(int j=i+1;j<li.Count;j++)
{
if(compareing(li[i],li[j])>0)
{
//if grater than it throw 1 else -1
temp = li[j];
li[j] = li[i];
li[i] = temp;
}
}
}
Console.WriteLine(li);
}
for (int i = 0; i < names.Length - 1; i++)
{
string temp = string.Empty;
for (int j = i + 1; j < names.Length; j++)
{
if (names[i][0] > names[j][0])
{
temp = names[i].ToString();
names[i] = names[j].ToString();
names[j] = temp;
}
}
}
for (int i = 0; i < names.Length - 1; i++)
{
int l = 0;
if (names[i][0] == names[i + 1][0])
{
string temp = string.Empty;
if (names[i].Length > names[i + 1].Length)
l = names[i + 1].Length;
else
l = names[i].Length;
for (int j = 0; j < l; j++)
{
if (names[i][j] != names[i + 1][j])
{
if (names[i][j] > names[i + 1][j])
{
temp = names[i].ToString();
names[i] = names[i + 1].ToString();
names[i + 1] = temp;
}
break;
}
}
}
}
foreach (var item in names)
{
Console.WriteLine(item.ToString());
}
string[] names = { "Flag", "Nest", "Cup", "Burg", "Yatch", "Next" };
string temp = "";
int tempX = 0, tempY = 0;
int tempX1 = 0, tempY1 = 0;
for (int i = 0; i<names.Length; i++)
{
for (int j = i+1; j<names.Length; j++)
{
if (((string)names[i])[0] > ((string)names[j])[0])
{
temp=(string)names[i];
names[i]=names[j];
names[j]=temp;
}
else if (((string)names[i])[0] == ((string)names[j])[0])
{
tempX=0; tempY=0;
tempX1=names[i].Length;
tempY1=names[j].Length;
while (tempX1 > 0 && tempY1 >0)
{
if (((string)names[i])[tempX] !=((string)names[j])[tempY])
{
if (((string)names[i])[tempX]>((string)names[j])[tempY])
{
temp=(string)names[i];
names[i]=names[j];
names[j]=temp;
break;
}
}
tempX++;
tempY++;
tempX1--;
tempY1--;
}
}
}
}
You can do it using bubble sort:
Assume you have the array of names called name
The tempName is just to not change the original array (You can use the original array instead)
void sortStudentsAlphabetically()
{
int nameIndex;
string temp;
string[] tempName = name;
bool swapped = true;
for(int i = 0; i < name.Length-1 && swapped ; i++)
{
swapped = false;
for(int j = 0; j < name.Length-1; j++)
{
nameIndex = 0;
recheck:
if (name[j][nameIndex]> name[j+1][nameIndex])
{
temp = tempName[j];
tempName[j] = tempName[j+1];
tempName[j+1] = temp;
swapped = true;
}
if (name[j][nameIndex] == name[j + 1][nameIndex])
{
nameIndex++;
goto recheck;
}
}
}
foreach(string x in tempName)
{
Console.WriteLine(x);
}
}
User Below code :
int[] arrayList = new int[] {2,9,4,3,5,1,7};
int temp = 0;
for (int i = 0; i <= arrayList.Length-1; i++)
{
for (int j = i+1; j < arrayList.Length; j++)
{
if (arrayList[i] > arrayList[j])
{
temp = arrayList[i];
arrayList[i] = arrayList[j];
arrayList[j] = temp;
}
}
}
Console.WriteLine("Sorting array in ascending order : ");
foreach (var item in arrayList)
{
Console.WriteLine(item);
}
Console.ReadLine();
Output:
Sorting array in ascending order : 1 2 3 4 5 7 9
I have some string in format like that
XXXX-XXXX-X_X_
All "_" should be replaced with Letters and numberst to prodce sth like that:
XXXX-XXXX-XAXA
XXXX-XXXX-XAXB
XXXX-XXXX-XAXC
XXXX-XXXX-XAXD
XXXX-XXXX-XAXE
XXXX-XXXX-XAXF
XXXX-XXXX-XAXG
(...)
XXXX-XXXX-XZX8
XXXX-XXXX-XZX9
XXXX-XXXX-X0XA
(...)
XXXX-XXXX-X2XA
XXXX-XXXX-X2XB
I know hoe to make it with one "_".
string alphaLetters = "ABCDEFGHIJKLMNOPQRSTUWXYZ0123456789ABCDEF";
foreach (char letter in alphaLetters.ToCharArray())
{
Numbers.Add(number.Replace('_', letter)));
}
I want this code to be working with unknown number of "_".
Can you help?
IMHO it must be recursive. (Note: that does not mean it must use recursive method call, although I used recursive call in the following code, it can be easily converted to internal recursion stack. )
public static void RunSnippet()
{
var r = new List<string>();
Replace("asd_asd_asd_".ToCharArray(), 0, r);
foreach(var s in r) { Console.WriteLine(s); }
}
public static char[] possibilities = new char[] { 'A', 'B', 'C' };
public static void Replace(char[] chars, int startIndex, IList<string> result)
{
for (int i = startIndex; i < chars.Length; i++)
{
if (chars[i] != '_')
{
continue;
}
// we found first '_'
for (int j = 0; j < possibilities.Length; j++)
{
chars[i] = possibilities[j];
Replace(chars, i + 1, result);
}
chars[i] = '_'; // take back what we replaced
return; //we're done here
}
// we didn't find any '_', so all were replaced and we have result:
result.Add(new string(chars));
}
Try this one:
var alphaIndexes = new List<int>();
string alphaLetters = "ABCDEFGHIJKLMNOPQRSTUWXYZ0123456789ABCDEF";
for(int n = 0; n<Numbers.Count; n++) {
char[] numberLetters = Numbers[n].ToCharArray();
int position = 0;
for(int i = numberLetters.Length - 1; i>=0; i--) {
if(numberLetters[i] == '_') {
int alphaIndex = 0;
if(alphaIndexes.Count <= position)
alphaIndexes.Add(0);
else {
alphaIndex = alphaIndexes[position];
}
numberLetters[i] = alphaLetters[alphaIndex];
position++;
}
}
if(alphaIndexes.Count > 0) {
alphaIndexes[0]++;
for(int j = 0; j < alphaIndexes.Count; j++) {
if(alphaIndexes[j] >= alphaLetters.Length) {
alphaIndexes[j] = 0;
if (j < alphaIndexes.Count)
alphaIndexes[j+1]++;
}
}
}
Numbers[n] = new String(numberLetters);
Numbers[n].Dump();
}