I'm trying to remove an element/item/entry from a split string.
Let's say I got the string [string_] as follows:
string string_ = "one;two;three;four;five;six";
Then I split this string to get each, let's say, item:
string[] item = (string_.Split(";"));
I have no informations other than from variables. Depending on the user choice, I can get an item value and index.
Let's say that for this example, the user chose "four" which is the index "3".
How can I make my string look like the index 3 have been deleted, as string_ would be equal to the following:
"one;two;three;five;six"
I've tried multiple things and it seems like the only solution is to go through a char method.
Is that true or did I miss something?
EDIT to suggested already_posted_answer :
Not quite the same question as my ITEM could be placed anywhere in my splitted string depending on the user selection.
First of all you need to write better variable names, string_ is a horrible name. Even something like "input" is way better.
string input = "one;two;three;four;five;six";
Next, you are on the right track by using Split(). This will return an array of string:
string[] splitInput = input.Split(";");
The resulting string array will look like this:
//string[0] = one
//string[1] = two
//string[2] = three
//string[3] = four
//string[4] = five
//string[5] = six
Removing with known index
If you want to remove a specific element from the array, you could make the result of Split() a List<T> by using ToList() instead and utilize the RemoveAt() method of the resulting List<T>:
List<string> splitList = input.Split(';').ToList();
splitList.RemoveAt(3);
//Re-create the string
string outputString = string.Join(";", splitList);
//output is: "one;two;three;five;six"
Remove all strings that match an input
If you need to remove items from the list without knowing their index but knowing the actual string, you can use LINQ's Where() to filter out the matching items:
//Get the input from the user somehow
string userInput = Console.ReadLine();
IEnumerable<string> filteredList = input.Split(';')
.Where(x => string.Compare(x, userInput, true) != 0);
//Re-create the string
string outputString = string.Join(";", filteredList);
I made a fiddle to demonstrate both methods here
You can convert an array of string to list by following:
var list = new List<string>(item);
Once the list is created, you can easily remove an element:
var index = list.IndexOf("four");
list.RemoveAt(index);
Join the string back:
var result = String.Join(";", list.ToArray());
Result:
You can convert your string array into a List<string>, and since you have the index of the item to be removed, you can remove the item using RemoveAt, then join the items back into one string.
Here's a complete console application example:
static void Main(string[] args)
{
string string_ = "one;two;three;four;five;six";
string[] items = (string_.Split(';'));
Console.WriteLine("Please select an item to remove:");
for (int i = 0;i<items.Length;i++)
{
Console.WriteLine(string.Format("{0}- {1}", (i + 1).ToString(), items[i]));
}
int num = 0;
int.TryParse(Console.ReadLine(), out num);
if (num > 0 && num <= items.Length)
{
List<string> itemsList = items.ToList();
itemsList.RemoveAt(num - 1);
string newString = string.Join(";", itemsList);
Console.WriteLine(string.Format("The new string is: {0}", newString));
}
else
{
Console.WriteLine("Invalid number!");
}
Console.ReadLine();
}
Hope that helps.
We can employ LINQ.
Initial plan is to split the string, then create a union of two enumerables: before and after the item. Something like this:
// preconditions
const int idx = 3;
string string_ = "one;two;three;four;five;six";
// actual transformation
string[] item = (string_.Split(';'));
var iterator = item.Take(idx).Concat(item.Skip(idx + 1));
// output the results
var result = string.Join(";", iterator);
Console.Write(result);
Would this work for you?
If you create a new string like this, then replace the value of string_ with the value of the new string.
string string_ = "one;two;three;four;five;six";
string newstring = string_.Replace("four", "");
string_ = newstring.Replace(";;", ";");
Related
I've the following string that I get from a method. I would like to parse it and make pairs. The order of input string will not change.
INPUT:
ku=value1,ku=value2,ku=value3,ku=value4,ku=value5,lu=value6,lu=value7,lu=value8,lu=value9
OUTPUT
Name value1
Title value2
School value3
.
.
.
Age value9
I think I can read through the string and assign value to the left hand side as I go and so on. However, I am very new to C#.
Use string.Split and split imput string to list key-value pair then split each pair to key and value. Tahts all.
You can do something like this:
void Main()
{
string str = "ku=value1,ku=value2,ku=value3,ku=value4,ku=value5,lu=value6,lu=value7,lu=value8,lu=value9";
var tempStr = str.Split(',');
var result = new List<KeyValue>();
foreach(var val in tempStr)
{
var temp = val.Split('=');
var kv = new KeyValue();
kv.Name = temp[0];
kv.Value = temp[1];
result.Add(kv);
}
}
public class KeyValue
{
public string Name {get;set;}
public string Value{get;set;}
}
If you don't need the first part you can do this using String split as follow
Split String on , using String.Split method creating sequence of string {"ku=value1","ku=value2",...}
Use Linq's Select method to apply an additional transformation
Use Split again on each item on the '=' character
Select the item to the right of the '=', at index 1 of the newly split item
Loop through everything and print your results
Here's the code
var target = "ku=value1,ku=value2,ku=value3,ku=value4,ku=value5,lu=value6,lu=value7,lu=value8,lu=value9";
var split = target.Split(',').Select(a=>a.Split('=')[1]).ToArray();
var names = new[]{"Name","Title","School",...,"Age"};
for(int i=0;i<split.Length;i++)
{
Console.WriteLine(names[i]+"\t"+split[i]);
}
If you want to find out more about how to use these methods you can look at the MSDN documentation for them :
String.Split(char[]) Method
Enumerable.Select Method
I suggest to try this way. Split() plus regular expression
string inputString = "ku=value1,ku=value2,ku=value3,ku=value4,ku=value5,lu=value6,lu=value7,lu=value8,lu=value9";
string pattern = "(.*)=(.*)";
foreach(var pair in inputString.Split(','))
{
var match = Regex.Match(pair,pattern);
Console.WriteLine(string.Format("{0} {1}",match.Groups[1].Value, match.Groups[2].Value));
}
I have a string like this
string myString = [0,4,5,5,6];
and i want to obtain each value of this string through a foreach loop for example , how i can proceed ?
Assuming you just forgot to put the quotes around the string:
you need to loop through each character and try to parse it into a number
//A list to hold the result
List<int> values = new List<int>();
//loop through each character 1 by 1
foreach(var c in myString)
{
//will hold the value
int num = 0;
//Try to parse the character into an integer
var isNumber = int.TryParse(c.ToString(), out num);
//if the parsing succeeded add it to the list
if(isNumber)
{
values.Add(num);
}
}
This will output the values 0,4,5,5,6 into the values list, ignoring all non numeric numbers
Why not just use linq like so
List<int> = myString.Select(Int32.Parse).ToList();
I want to remove comma separated duplicate string values like :
String str = "2,4,3,12,25,2,4,3,6,2,2,2";
And i want to output like this:
String str1 = "6,2";
please tell how to do this i'll my self but i can't solve this
A wild ride with Linq. Probably there is a better way, but this is the first one I could think of.
string str = "2,4,3,12,25,2,4,3,6,2,2,2";
List<string> uniques = str.Split(',').Reverse().Distinct().Take(2).Reverse().ToList();
string newStr = string.Join(",", uniques);
Console.WriteLine(newStr);
Split the string at the comma to get the sequence
Apply the Reverse op, you get 2 2 2 6 .... 4 2
Apply the Distinct, you get 2,6,3,4,25,12
Take the first 2 elements (2,6)
Reverse them 6,2
Join in a new string with the comma sep.
Pretty basic but works in your case
String str = "2,4,3,12,25,2,4,3,6,2,2,2";
String[] arr = str.Split(',');
String penultimate = "";
String ultimate = "";
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] != ultimate)
{
penultimate = ultimate;
ultimate = arr[i];
}
}
Console.WriteLine("{0},{1}", penultimate, ultimate);
Here is a suggestion:
string item = "";
var lastTwoUnique= str.Split(',') //split the string on ,
//now, take the next element from the array as long as it's
//not equal to the previous element (which we store in item)
.Where((st) => st==item ? false : (item = st) == item) //** see comment below
.Reverse() //reverse collection
.Take(2) //take two (two last)
.Reverse() //reverse back
.ToList(); //make it a list
var answer = string.Join(",", lastTwoUnique);
This solution keeps the data intact, so if you want you could store the unique list, then do many queries on that list. Solutions using Distinct() will, for instance, not keep every occurrence of 2 in the list.
This solution has the intermediate result (after Where) of: 2,4,3,12,25,2,4,3,6,2. While distinct will be:2,4,3,12,25,6
** The line .Where((st) => st==item ? false : (item = st) == item) may seem odd, so let me explain:
Where takes a lambda function that returns true for items that should be taken, and false for the items that should be ignored. So st will become each sub string from the Split.
Now, let's investigate the actual function:
st==item //is this st equal to the previous item?
? false //then return false
: (item = st) == item //if it's not equal, then assign `item` to the current `st`
//and compare that to item and get `true`
You could use the .Distinct() extension method.
String str = "2,4,3,12,25,2,4,3,6,2,2,2";
var oldArray=str.Split(',').Reverse();
var collectionWithDistinctElements = oldArray.Distinct().ToArray();
var reverse=collectionWithDistinctElements.Reverse();
//take two element
var twoElements=reverse.ToList().Take(2);
//last join them
var resultArray=string.Join(",", twoElements);
Another solution, which I've attempted to keep quite simple:
String str = "2,4,3,12,25,2,4,3,6,2,2,2";
var holder = new string[2];
foreach (var x in str.Split(','))
{
if(holder.Last() != x)
{
holder[0] = holder[1];
holder[1] = x;
}
}
var result = string.Join(",", holder);
This will iterate over the comma-separated items, all the time keeping the two last seen distinct items in holder.
String str = "2,4,3,12,25,2,4,3,6,2,2,2";
string str = s1;
var uniques = str.Split(',').Reverse().Distinct().Take(3).Reverse().Take(2).ToList();
string newStr = string.Join(",", uniques.ToArray());
This will give me correct output that is 3,6 thats i want.
Thanks to all the Guys that give me ans.
This will definitely work
string str = "2,4,3,12,25,2,4,3,6,2,2,2";
List<string> uniques = new List<string>()
uniques = str.Split(',').Reverse().Distinct().Take(2).Reverse().ToList();
string newStr = string.Join(",", uniques);
I know this question would have been asked infinite number of times, but I'm kinda stuck.
I have a string something like
"Doc1;Doc2;Doc3;12"
it can be something like
"Doc1;Doc2;Doc3;Doc4;Doc5;56"
Its like few pieces of strings separated by semicolon, followed by a number or id.
I need to extract the number/id and the strings separately.
To be exact, I can have 2 strings: one having "Doc1;Doc2;Doc3" or "Doc1;Doc2;Doc3;Doc4" and the other having just the number/id as "12" or "34" or "45" etc.
And yeah I am using C# 3.5
I understand its a pretty easy and witty question, but this guy is stuck.
Assistance required from experts.
Regards
Anurag
string.LastIndexOf and string.Substring are the keys to what you're trying to do.
var str = "Doc1;Doc2;Doc3;12";
var ind = str.LastIndexOf(';');
var str1 = str.Substring(0, ind);
var str2 = str.Substring(ind+1);
One way:
string[] tokens = str.Split(';');
var docs = tokens.Where(s => s.StartsWith("Doc", StringComparison.OrdinalIgnoreCase));
var numbers = tokens.Where(s => s.All(Char.IsDigit));
String docs = s.Substring(0, s.LastIndexOf(';'));
String number = s.Substring(s.LastIndexOf(';') + 1);
One possible approach would be this:
var ids = new List<string>();
var nums = new List<string>();
foreach (var s in input.Split(';'))
{
int val;
if (!int.TryParse(s, out val)) { ids.Add(s); }
else { nums.Add(s); }
}
where input is something like Doc1;Doc2;Doc3;Doc4;Doc5;56. Now, ids will house all of the Doc1 like values and nums will house all of the 56 like values.
you can use StringTokenizer functionality.
http://www.c-sharpcorner.com/UploadFile/pseabury/JavaLikeStringTokenizer11232005015829AM/JavaLikeStringTokenizer.aspx
split string using ";"
StringTokenizer st = new StringTokenizer(src1,";");
collect final String. that will be your ID.
You may try one of two options: (assuming your input string is in string str;
Approach 1
Get LastIndexOf(';')
Split the string based on the index. This will give you string and int part.
Split the string part and process it
Process the int part
Approach 2
Split the string on ;
Run a for loop - for (int i = 0; i < str.length - 2; i++) - this is the string part
Process str[length - 1] separately - this is the int part
Please take this as a starting point as there could be other approaches to implement a solution for this
string actual = "Doc1;Doc2;Doc3;12";
int lstindex = actual.LastIndexOf(';');
string strvalue = actual.Substring(0, lstindex);
string id = actual.Substring(lstindex + 1);
I cannot believe I am having trouble with this following string
String filter = "name=Default;pattern=%%;start=Last;end=Now";
This is a short and possibly duplicate question, but how would I split this string to get:
string Name = "Default";
string Pattern = "%%" ;
string start = "Last" ;
string end = "Now" ;
Reason why I ask is my deadline is very soon, and this is literally the last thing I must do. I'm Panicking, and I'm stuck on this basic command. I tried:
pattern = filter.Split(new string[] { "pattern=", ";" },
StringSplitOptions.RemoveEmptyEntries)[1]; //Gets the pattern
startDate = filter.Split(new string[] { "start=", ";" },
StringSplitOptions.RemoveEmptyEntries)[1]; //Gets the start date
I happen to get the pattern which I needed, but as soon as I try to split start, I get the value as "Pattern=%%"
What can I do?
Forgot to mention
The list in this string which needs splitting may not be in any particular order . this is a single sample of a string which will be read out of a stringCollection (reading these filters from Properties.Settings.Filters
Using string.Split this is a two stage process.
In the first case split on ; to get an array of keyword and value pairs:
string[] values = filter.Split(';');
Then loop over the resultant list splitting on = to get the keywords and values:
foreach (string value in values)
{
string[] pair = value.Split('=');
string key = pair[0];
string val = pair[1];
}
String filter = "name=Default;pattern=%%;start=Last;end=Now";
string[] temp = filter.Split('=');
string name = temp[1].Split(';')[0];
string pattern = temp[2].Split(';')[0];
string start = temp[3].Split(';')[0];
string end = temp[4].Split(';')[0];
This should do the trick:
string filter = "name=Default;pattern=%%;start=Last;end=Now";
// Make a dictionary.
var lookup = filter
.Split(';')
.Select(keyValuePair => keyValuePair.Split('='))
.ToDictionary(parts => parts[0], parts => parts[1]);
// Get values out of the dictionary.
string name = lookup["name"];
string pattern = lookup["pattern"];
string start = lookup["start"];
string end = lookup["end"];
The start date ends up at the thrird position in the array:
startDate = filter.Split(new string[] { "start=", ";" }, StringSplitOptions.RemoveEmptyEntries)[2];
Instead of splitting the string once for each value, you might want to split it into the separate key-value pairs, then split each pair:
string[] pairs = filter.Split(';');
string[] values = pairs.Select(pair => pair.Split('=')[1]).ToArray();
string name = values[0];
string pattern = values[1];
string start = values[2];
string end = values[3];
(This code of course assumes that the key-value pairs always come in the same order.)
You could also split the string into intersperced array, so that every other item is a key or a value:
string[] values = filter.Split(new string[] { "=", ";" }, StringSplitOptions.None);
string name = values[1];
string pattern = values[3];
string start = values[5];
string end = values[7];
Edit:
To handle key-values in any order, make a lookup from the string, and pick values from it:
ILookup<string, string> values =
filter.Split(';')
.Select(s => s.Split('='))
.ToLookup(p => p[0], p => p[1]);
string name = values["name"].Single();
string pattern = values["pattern"].Single();
string start = values["start"].Single();
string end = values["end"].Single();
You can use SingleOrDefault if you want to support values being missing from the string:
string name = values["name"].SingleOrDefault() ?? "DefaultName";
The lookup also supports duplicate key-value pairs. If there might be duplicates, just loop through the values:
foreach (var string name in values["name"]) {
// do something with the name
}
Well I tried something like this:
var result = "name=Default;pattern=%%;start=Last;end=Now".Split(new char[]{'=',';'});
for(int i=0;i<result.Length; i++)
{
if(i%2 == 0) continue;
Console.WriteLine(result[i]);
}
and the output is:
Default
%%
Last
Now
Is this what you want?
You see, the thing is now that your Split on filter a second time still starts from the beginning of the string, and it matches against ;, so since the string hasn't changed, you still retrieve previous matches (so your index accessor is off by X).
You could break this down into it's problem parts, such that:
var keyValues = filter.Split(';');
var name = keyValues[0].Split('=')[1];
var pattern = keyValues[1].Split('=')[1];
var start = keyValues[2].Split('=')[1];
var end = keyValues[3].Split('=')[1];
Note that the above code is potentially prone to error, and as such should be properly altered.
You can use the following:
String filter = "name=Default;pattern=%%;start=Last;end=Now";
string[] parts = filter.Split(';');
string Name = parts[0].Substring(parts[0].IndexOf('=') + 1);
string Pattern = parts[1].Substring(parts[1].IndexOf('=') + 1);
string start = parts[2].Substring(parts[2].IndexOf('=') + 1);
string end = parts[3].Substring(parts[3].IndexOf('=') + 1);
Use this:
String filter = "name=Default;pattern=%%;start=Last;end=Now";
var parts = filter.Split(';').Select(x => x.Split('='))
.Where(x => x.Length == 2)
.Select(x => new {key = x[0], value=x[1]});
string name = "";
string pattern = "";
string start = "";
string end = "";
foreach(var part in parts)
{
switch(part.key)
{
case "name":
name = part.value;
break;
case "pattern":
pattern = part.value;
break;
case "start":
start = part.value;
break;
case "end":
end = part.value;
break;
}
}
If you don't need the values in named variables, you only need the second line. It returns an enumerable with key/value pairs.
My solution has the added benefits that the order of those key/value pairs in the string is irrelevant and it silently ignores invalid parts instead of crashing.
I found a simple solution on my own too. Most of your answers would have worked if the list would have been in the same order every single time, but it wont be. the format however, will always stay the same. The solution is a simple iteration using a foreach loop, and then checking if it starts with a certain word, namely, the word I am looking for, like Name, Pattern etc.
Probably not the most cpu efficient way of doing it, but it is C# for dummies level. Really brain-fade level.
Here is my beauty.
foreach (string subfilter in filter.Split(';')) //filter.Split is a string [] which can be iterated through
{
if (subfilter.ToUpper().StartsWith("PATTERN"))
{
pattern = subfilter.Split('=')[1];
}
if (subfilter.ToUpper().StartsWith("START"))
{
startDate = subfilter.Split('=')[1];
}
if (subfilter.ToUpper().StartsWith("END"))
{
endDate = subfilter.Split('=')[1];
}
}