I am trying to iterate over an array of strings and check/replace if any of the strings exist in the input string. Using LINQ, this is what i have so far.
string input = "/main/dev.website.com"
string[] itemsToIgnore = { "dev.", "qa.", "/main/" };
string website = itemsToIgnore
.Select(x =>
{ x = input.Replace(x, ""); return x; })
.FirstOrDefault();
When i run this, nothing actually happens and my input string stays the same?
string website = itemsToIgnore
.Aggregate(input, (current, s) =>
current.StartsWith(s) ? current.Replace(s, string.Empty) : current);
and without Linq
foreach (var part in itemsToIgnore)
{
if (website.StartsWith(part))
{
website = website.Replace(part, string.Empty);
}
}
Related
I'm trying to remove the duplicate combination from a csv file.
I tried using Distinct but it seems to stay the same.
string path;
string newcsvpath = #"C:\Documents and Settings\MrGrimm\Desktop\clean.csv";
OpenFileDialog openfileDial = new OpenFileDialog();
if (openfileDial.ShowDialog() == DialogResult.OK)
{
path = openfileDial.FileName;
var lines = File.ReadLines(path);
var grouped = lines.GroupBy(line => string.Join(", ", line.Split(',').Distinct())).ToArray();
var unique = grouped.Select(g => g.First());
var buffer = new StringBuilder();
foreach (var name in unique)
{
string value = name;
buffer.AppendLine(value);
}
File.WriteAllText(newcsvpath ,buffer.ToString());
label5.Text = "Complete";
}
For example, I have a combination of
{ 1,1,1,1,1,1,1,1 } { 1,1,1,1,1,1,1,2 }
{ 2,1,1,1,1,1,1,1 } { 1,1,1,2,1,1,1,1 }
The output should be
{ 1,1,1,1,1,1,1,1 }
{ 2,1,1,1,1,1,1,1 }
From you example, it seems that you want to treat each line as a sequence of numbers and that you consider two lines equal if one sequence is a permutation of the other.
So from reading your file, you have:
var lines = new[]
{
"1,1,1,1,1,1,1,1",
"1,1,1,1,1,1,1,2",
"2,1,1,1,1,1,1,1",
"1,1,1,2,1,1,1,1"
};
Now let's convert it to an array of number sequences:
var linesAsNumberSequences = lines.Select(line => line.Split(',')
.Select(int.Parse)
.ToArray())
.ToArray();
Or better, since we are not interested in permutations, we can sort the numbers in the sequences immediately:
var linesAsSortedNumberSequences = lines.Select(line => line.Split(',')
.Select(int.Parse)
.OrderBy(number => number)
.ToArray())
.ToArray();
When using Distinct on this, we have to pass a comparer which considers two array equal, if they have the same elements. Let's use the one from this SO question
var result = linesAsSortedNumberSequences.Distinct(new IEnumerableComparer<int>());
Try it
HashSet<string> record = new HashSet<string>();
foreach (var row in dtCSV.Rows)
{
StringBuilder textEditor= new StringBuilder();
foreach (string col in columns)
{
textEditor.AppendFormat("[{0}={1}]", col, row[col].ToString());
}
if (!record.Add(textEditor.ToString())
{
}
}
Here is my string:
www.stackoverflow.com/questions/ask/user/end
I split it with / into a list of separated words:myString.Split('/').ToList()
Output:
www.stackoverflow.com
questions
ask
user
end
and I need to rejoin the string to get a list like this:
www.stackoverflow.com
www.stackoverflow.com/questions
www.stackoverflow.com/questions/ask
www.stackoverflow.com/questions/ask/user
www.stackoverflow.com/questions/ask/user/end
I think about linq aggregate but it seems it is not suitable here. I want to do this all through linq
You can try iterating over it with foreach
var splitted = "www.stackoverflow.com/questions/ask/user/end".Split('/').ToList();
string full = "";
foreach (var part in splitted)
{
full=$"{full}/{part}"
Console.Write(full);
}
Or use linq:
var splitted = "www.stackoverflow.com/questions/ask/user/end".Split('/').ToList();
var list = splitted.Select((x, i) => string.Join("/", a.Take(i + 1)));
Linq with side effect:
string prior = null;
var result = "www.stackoverflow.com/questions/ask/user/end"
.Split('/')
.Select(item => prior == null
? prior = item
: prior += "/" + item)
.ToList();
Let's print it out
Console.WriteLine(string.Join(Environment.NewLine, result));
Outcome:
www.stackoverflow.com
www.stackoverflow.com/questions
www.stackoverflow.com/questions/ask
www.stackoverflow.com/questions/ask/user
www.stackoverflow.com/questions/ask/user/end
Linq without side effects ;)
Enumerable.Aggregate can be used here if we use List<T> as a result.
var raw = "www.stackoverflow.com/questions/ask/user/end";
var actual =
raw.Split('/')
.Aggregate(new List<string>(),
(list, word) =>
{
var combined = list.Any() ? $"{list.Last()}/{word}" : word;
list.Add(combined);
return list;
});
without Linq write below code,
var str = "www.stackoverflow.com/questions/ask/user/end";
string[] full = str.Split('/');
string Result = string.Empty;
for (int i = 0; i < full.Length; i++)
{
Console.WriteLine(full[i]);
}
for (int i = 0; i < full.Length; i++)
{
if (i == 0)
{
Result = full[i];
}
else
{
Result += "/" + full[i];
}
Console.WriteLine(Result);
}
I have 3 string ---
m60_CLDdet2_LOSS2CLF_060520469434_R0RKE_52_GU
m60_CLDdet2_LOSS2CLF_060520469434_R10KE_52_TCRER
m60_CLDdet2_LOSS2CLF_060520469434_R0HKE_52_NT
and I want R0RKE_52_GU, R10KE_52_TCRER,R0HKE_52_NT.
Note: m60_CLDdet2_LOSS2CLF_060520469434 is varying so I want to find substring if R0RKE or R10KE or R0HKE exists
I would suggest using a Regular expression for this, it is much more versatile for pattern matching.
var matches = System.Text.RegularExpressions.Regex.Matches(text, #"(R0RKE|R10KE|R0HKE).*");
I want to find substring if R0RKE or R10KE or R0HKE exists
This LINQ query returns the desired result:
var strings=new[]{"m60_CLDdet2_LOSS2CLF_060520469434_R0RKE_52_GU","m60_CLDdet2_LOSS2CLF_060520469434_R10KE_52_TCRER","m60_CLDdet2_LOSS2CLF_060520469434_R0HKE_52_NT"};
string[] starts = { "R0RKE", "R10KE", "R0HKE" };
var result = strings
.Select(str => new { str, match = starts.FirstOrDefault(s => str.IndexOf("_" + s) >= 0)})
.Where(x => x.match != null)
.Select(x => x.str.Substring(x.str.IndexOf(x.match)));
Console.Write(String.Join(",", result)); // R0RKE_52_GU,R10KE_52_TCRER,R0HKE_52_NT
I write it into static method:
private static string TakeIt(string inputString)
{
if (!Regex.IsMatch(inputString, "(R0RKE|R10KE|R0HKE)"))
{
return string.Empty;
}
var regex = new Regex(#"_");
var occurances = regex.Matches(inputString);
var index = occurances[3].Index + 1;
return inputString.Substring(index, inputString.Length - index);
}
void Main()
{
var string1 = "m60_CLDdet2_LOSS2CLF_060520469434_R0RKE_52_GU";
var string2 = "m60_CLDdet2_LOSS2CLF_060520469434_R10KE_52_TCRER";
var string3 = "m60_CLDdet2_LOSS2CLF_060520469434_R0HKE_52_NT";
var string4 = "m60_CLDdet2_LOSS2CLF_060520469434_hhhhh";
Console.WriteLine(TakeIt(string1));
Console.WriteLine(TakeIt(string2));
Console.WriteLine(TakeIt(string3));
Console.WriteLine(TakeIt(string4));
}
Hope this help.
Update: added .Any - it simplifies the code and it's just as same efficient.
If you just need to check for three strings inside string array you can do :
static string[] GetStrings(string[] dirty, string[] lookUpValues)
{
List<string> result = new List<string>();
for (int i = 0; i < dirty.Length; i++) if (lookUpValues.Any(dirty[i].Contains)) result.Add(dirty[i]);
return result.ToArray();
}
Usage: string[] result = GetStrings(dirty, new[] {"R0RKE", "R10KE", "R0HKE"});
Also you can use LINQ query and Regex.Matches as others advised.
I want to find a string of fixed length with specific substring. But I need to do it like we can do in SQL queries.
Example:
I have strings like -
AB012345
AB12345
AB123456
AB1234567
AB98765
AB987654
I want to select strings that have AB at first and 6 characters afterwards. Which can be done in SQL by SELECT * FROM [table_name] WHERE [column_name] LIKE 'AB______' (6 underscores after AB).
So the result will be:
AB012345
AB123456
AB987654
I need to know if there is any way to select strings in such way with C#, by using AB______.
You can use Regular Expressions to filter the result:
List<string> sList = new List<string>(){"AB012345",
"AB12345",
"AB123456",
"AB1234567",
"AB98765",
"AB987654"};
var qry = sList.Where(s=>Regex.Match(s, #"^AB\d{6}$").Success);
Considering you have an string array:
string[] str = new string[3]{"AB012345", "A12345", "AB98765"};
var result = str.Where(x => x.StartsWith("AB") && x.Length == 8).ToList();
The logic is if it starts with AB, and its length is 8. It is your best match.
this should do it
List<string> sList = new List<string>(){
"AB012345",
"AB12345",
"AB123456",
"AB1234567",
"AB98765",
"AB987654"};
List<string> sREsult = sList.Where(x => x.Length == 8 && x.StartsWith("AB")).ToList();
first x.Length == 8 determines the length and x.StartsWith("AB") determines the required characters at the start of the string
This can be achieved by using string.Startwith and string.Length function like this:
public bool CheckStringValid (String input)
{
if (input.StartWith ("AB") && input.Length == 8)
{
return true;
}
else
{
return false;
}
}
This will return true if string matches your criteria.
Hope this helps.
var strlist = new List<string>()
{
"AB012345",
"AB12345",
"AB123456",
"AB1234567",
"AB98765",
"AB987654"
};
var result = strlist.Where(
s => (s.StartsWith("AB") &&(s.Length == 8))
);
foreach(var v in result)
{
Console.WriteLine(v.ToString());
}
I have a delimited string that I need sorted. First I need to check if 'Francais' is in the string, if so, it goes first, then 'Anglais' is next, if it exists. After that, everything else is alphabetical. Can anyone help me? Here's what I have so far, without the sorting
private string SortFrench(string langs)
{
string _frenchLangs = String.Empty;
string retval = String.Empty;
_frenchLangs = string.Join(" ; ",langs.Split(';').Select(s => s.Trim()).ToArray());
if (_frenchLangs.Contains("Francais"))
retval += "Francais";
if (_frenchLangs.Contains("Anglais"))
{
if (retval.Length > 0)
retval += " ; ";
retval += "Anglais";
}
//sort the rest
return retval;
}
Someone liked my comment, so figured I'd go ahead and convert that into your code:
private string SortFrench(string langs)
{
var sorted = langs.Split(';')
.Select(s => s.Trim())
.OrderByDescending( s => s == "Francais" )
.ThenByDescending( s => s == "Anglais" )
.ThenBy ( s => s )
.ToArray();
return string.Join(" ; ",sorted);
}
My syntax may be off slightly as I've been in the Unix world for awhile now and haven't used much LINQ lately, but hope it helps.
Here's what I came up with. You could change the .Sort() for a OrderBy(lang => lang) after the Select, but I find it's cleaner that way.
public string SortLanguages(string langs)
{
List<string> languages = langs.Split(';').Select(s => s.Trim()).ToList();
languages.Sort();
PlaceAtFirstPositionIfExists(languages, "anglais");
PlaceAtFirstPositionIfExists(languages, "francais");
return string.Join(" ; ", languages);
}
private void PlaceAtFirstPositionIfExists(IList<string> languages, string language)
{
if (languages.Contains(language))
{
languages.Remove(language);
languages.Insert(0, language);
}
}
You should use a custom comparer class
it will allow you to use the built in collection sorting functions, or the linq OrderBy using your own criteria
Try this:
private string SortFrench(string langs)
{
string _frenchLangs = String.Empty;
List<string> languages = langs
.Split(';')
.Select(s => s.Trim())
.OrderBy(s => s)
.ToList();
int insertAt = 0;
if (languages.Contains("Francais"))
{
languages.Remove("Francais");
languages.Insert(insertAt, "Francais");
insertAt++;
}
if(languages.Contains("Anglais"))
{
languages.Remove("Anglais");
languages.Insert(insertAt, "Anglais");
}
_frenchLangs = string.Join(" ; ", languages);
return _frenchLangs;
}
All can be done in single line
private string SortFrench(string langs)
{
return string.Join(" ; ", langs.Split(';').Select(s => s.Trim())
.OrderBy(x => x != "Francais")
.ThenBy(x => x != "Anglais")
.ThenBy(x=>x));
}
Sorting alphabetically is simple; adding .OrderBy(s => s) before that .ToArray() will do that. Sorting based on the presence of keywords is trickier.
The quick and dirty way is to split into three:
Strings containing "Francais": .Where(s => s.Contains("Francais")
Strings containing "Anglais": .Where(s => s.Contains("Anglais")
The rest: .Where(s => !francaisList.Contains(s) && !anglaisList.Contains(s))
Then you can sort each of these alphabetically, and concatenate them.
Alternatively, you can implement IComparer using the logic you described:
For strings A and B:
If A contains "Francais"
If B contains "Francais", order alphabetically
Else
If B contains "Francais", B goes first
Else
If A contains "Anglais"
If B contains "Anglais", order alphabetically
Else, A goes first
Else, order alphabetically
There may be room for logical re-arrangement to simplify that. With all that logic wrapped up in a class that implements IComparer, you can specify that class for use by .OrderBy() to have it order your query results based on your custom logic.
You can also use Array.Sort(yourStringArray)
This code creates a list of the languages, sorts them using a custom comparer, and then puts the sorted list back together:
const string langs = "foo;bar;Anglais;Francais;barby;fooby";
var langsList = langs.Split(';').ToList();
langsList.Sort((s1, s2) =>
{
if (s1 == s2)
return 0;
if (s1 == "Francais")
return -1;
if (s2 == "Francais")
return 1;
if (s1 == "Anglais")
return -1;
if (s2 == "Anglais")
return 1;
return s1.CompareTo(s2);
});
var sortedList = string.Join(";", langsList);
Console.WriteLine(sortedList);
This way you can set any list of words in front:
private static string SortFrench(string langs, string[] setStartList)
{
string _frenchLangs = String.Empty;
List<string> list = langs.Split(';').Select(s => s.Trim()).ToList();
list.Sort();
foreach (var item in setStartList){
if (list.Contains(item))
{
list.Remove(setFirst);
}
}
List<string> tempList = List<string>();
tempList.AddRange(setStartList);
tempList.AddRange(list);
list = tempList;
_frenchLangs = string.Join(" ; ", list);
return _frenchLangs;
}