Search for substring in an item of List - c#

I have list :
List<string> str = new List<string>();
str.Add("asdf---US,IN");
str.Add("asdg---UK,IN");
str.Add("asjk---RU,IN");
str.Add("asrt---IT,DE");
I want to get List like ("asdf","asdg","asjk") when i enter "IN". For this i'm doing :
System.Text.RegularExpressions.Regex regEx =
new System.Text.RegularExpressions.Regex("asr",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
List<string> str = new List<string>();
str.Add("asdf---US,IN");
str.Add("asdg---UK,IN");
str.Add("asjk---RU,IN");
str.Add("asrt---IT,DE");
var getArray = str.Where<string>(item => regEx.IsMatch(item)).ToList<string>();
str = getArray.ToList();
str is having correct result. but it is containing whole item like "asdf---US,IN","asdg---UK,IN", "asjk---RU,IN". I only want first four character in item in list i.e., 'asdf", "asdg", "asjk". What condition can i put in lambda expression, to get list i want?

If its only going to be first four characters use string.SubString:
var getArray = str.Where(item => regEx.IsMatch(item))
.Select(r=> r.Substring(0,4))
.ToList();
You also doesn't need to specify <string> cast with where and ToList. Items in your list are already of type string.
EDIT:
If you are only looking for those strings that ends with "IN" you may get rid of the regex and use string.EndsWith:
var getArray = str.Where(item => item.EndsWith("IN"))
.Select(r=> r.Substring(0,4))
.ToList();

The regex should be
.*?(?=---.*?IN)
and the query should be
var getArray = str.Where<string>(item => regEx.IsMatch(item)).Select<string>(item => regEx.Match(item)).ToList<string>();

Related

List<comma-separated strings> => List<string>?

Trying to come up with a LINQy way to do this, but nothing's coming to me.
I have a List<> of objects which include a property which is a comma-separated list of alpha codes:
lst[0].codes = "AA,BB,DD"
lst[1].codes = "AA,DD,EE"
lst[2].codes = "GG,JJ"
I'd like a list of those codes, hopefully in the form of a List of strings:
result = AA,BB,DD,EE,GG,JJ
Thanks for any direction.
Use SelectMany to get all split codes and use Distinct to not repeat the values.
Try something like this:
var result = lst.SelectMany(x => x.codes.Split(",")).Distinct().ToList();
You need to use Split to split each string into multiple strings. Then you need to use SelectMany to concatenate multiple sequences into a single sequence, and then you need to use Distinct to remove duplicates.
var result =
lst
.SelectMany(x => x.codes.Split(','))
.Distinct()
.ToList();
if you need a string as a result:
string result = string.Join(",",lst.SelectMany(p=>p.codes.Split(",")).Distinct());
Try this:
List<string> list = new List<string>();
char[] sep = new char[1];
sep[0] = ',';
foreach (string item in lst)
{
list.AddRange(item.Split(sep));
}
list = list.Distinct().ToList();

Order of groups with dynamic linq

Somewhat similar to this question:
Where do I put the "orderby group.key" in this LINQ statement?
Except I'm using Dynamic.Linq which makes this a bit harder. I have a bunch of data coming from a database and then I'm grouping by some field and then outputing the result. The problem is that the ordering of the groups seems to randomly jump around which isn't very convenient for the end-user. So taking inspiration from the linked question, if I had this:
string[] words = { "boy","car", "apple", "bill", "crow", "brown" };
// note the first non-dynamic select here was just because I don't think dynamic linq
// will support indexing a string like that and it's not an important detail anyway
var wordList = words.Select(w => new {FirstLetter = w[0], Word = w})
.GroupBy("new (FirstLetter)","Word");
foreach(IGrouping<object, dynamic> g in wordList)
{
Console.WriteLine("Words that being with {0}:",
g.Key.ToString().ToUpper());
foreach (var word in g)
Console.WriteLine(" " + word);
}
Console.ReadLine();
How would I get it to order the keys? At least part of the problem is that the dynamic GroupBy returns an IEnumerable. I thought it might be as easy as:
var wordList = words.Select(w => new {FirstLetter = w[0], Word = w})
.GroupBy("new (FirstLetter)","Word")
.OrderBy("Key");
But that gives me a System.ArgumentException (At least one object must implement IComparable.) when it hits the foreach loop.
My actual code in my project is a little more complicated and looks something like this:
var colGroup = row.GroupBy(string.Format("new({0})",
string.Join(",", c)), string.Format("new({0})",
string.Join(",", v)));
Where c is a list of strings that I need to group by and v is a list of strings that I need to select in each group.
Ok - this is one way to do it, but it might be a little to static to be useful. The problem is that I had this part:
.GroupBy("new (FirstLetter)","Word");
Using new because I can't use a value type as a key (I had another question about that: https://stackoverflow.com/a/26022002/1250301). When with the OrderBy("Key") part, the problem is that it doesn't have a way to compare those dynamic types. I could solve it like this:
var wordList = words.Select(w => new {FirstLetter = w[0].ToString(), Word = w})
.GroupBy("FirstLetter","Word")
.OrderBy("Key");
Making the key a string. Or like this:
var wordList = words.Select(w => new {FirstLetter = w[0], Word = w})
.GroupBy("new (FirstLetter as k)","Word")
.OrderBy("Key.k");
Making it order by something (a char) that is comparable.
I can make it work with my actual problem like this (but it's kind of ugly):
var colGroup = row.GroupBy(string.Format("new({0})", string.Join(",", c)),
string.Format("new({0})", string.Join(",", v)))
.OrderBy(string.Join(",", c.Select(ob => string.Format("Key.{0}", ob))));
I am not sure what you are trying to do, but is that syntax even compiling?
try:
string[] words = { "boy","car", "apple", "bill", "crow", "brown" };
var wordList = words.Select(w => new {FirstLetter = w[0], Word = w})
.GroupBy(x => x.FirstLetter, x => x.Word)
.OrderBy(x => x.Key);

How can I remove numbers/digits from strings in a List<string>?

I have a List of strings:
List<string> _words = ExtractWords(strippedHtml);
_words contains 1799 indexes; in each index there is a string.
Some of the strings contain only numbers, for example:
" 2" or "2013"
I want to remove these strings and so in the end the List will contain only strings with letters and not digits.
A string like "001hello" is OK but "001" is not OK and should be removed.
You can use LINQ for that:
_words = _words.Where(w => w.Any(c => !Char.IsDigit(c))).ToList();
This would filter out strings that consist entirely of digits, along with empty strings.
_words = _words.Where(w => !w.All(char.IsDigit))
.ToList();
For removing words that are only made of digits and whitespace:
var good = new List<string>();
var _regex = new Regex(#"^[\d\s]*$");
foreach (var s in _words) {
if (!_regex.Match(s).Success)
good.Add(s);
}
If you want to use LINQ something like this should do:
_words = _words.Where(w => w.Any(c => !char.IsDigit(c) && !char.IsWhiteSpace(c)))
.ToList();
You can use a traditional foreach and Integer.TryParse to detect numbers.
This will be faster than Regex or LINQ.
var stringsWithoutNumbers = new List<string>();
foreach (var str in _words)
{
int n;
bool isNumeric = int.TryParse(str, out n);
if (!isNumeric)
{
stringsWithoutNumbers.Add(str);
}
}

Get Count in List of instances contained in a string

I have a string containing up to 9 unique numbers from 1 to 9 (myString) e.g. "12345"
I have a list of strings {"1"}, {"4"} (myList) .. and so on.
I would like to know how many instances in the string (myString) are contained within the list (myList), in the above example this would return 2.
so something like
count = myList.Count(myList.Contains(myString));
I could change myString to a list if required.
Thanks very much
Joe
I would try the following:
count = mylist.Count(s => myString.Contains(s));
It is not perfectly clear what you need, but these are some options that could help:
myList.Where(s => s == myString).Count()
or
myList.Where(s => s.Contains(myString)).Count()
the first would return the number of strings in the list that are the same as yours, the second would return the number of strings that contain yours. If neither works, please make your question more clear.
If myList is just List<string>, then this should work:
int count = myList.Count(x => myString.Contains(x));
If myList is List<List<string>>:
int count = myList.SelectMany(x => x).Count(s => myString.Contains(s));
Try
count = myList.Count(s => s==myString);
This is one approach, but it's limited to 1 character matches. For your described scenario of numbers from 1-9 this works fine. Notice the s[0] usage which refers to the list items as a character. For example, if you had "12" in your list, it wouldn't work correctly.
string input = "123456123";
var list = new List<string> { "1", "4" };
var query = list.Select(s => new
{
Value = s,
Count = input.Count(c => c == s[0])
});
foreach (var item in query)
{
Console.WriteLine("{0} occurred {1} time(s)", item.Value, item.Count);
}
For multiple character matches, which would correctly count the occurrences of "12", the Regex class comes in handy:
var query = list.Select(s => new
{
Value = s,
Count = Regex.Matches(input, s).Count
});
try
var count = myList.Count(x => myString.ToCharArray().Contains(x[0]));
this will only work if the item in myList is a single digit
Edit: as you probably noticed this will convert myString to a char array multiple times so it would be better to have
var myStringArray = myString.ToCharArray();
var count = myList.Count(x => myStringArray.Contains(x[0]));

Get records which do not start with an alphabetical character in linq

I need to get a list of records that do not start with an alphabetical character, i.e. which either starts with a numerical character or any special character.
Whats the simple LINQ query to get this list?
List<string> Entries = new List<string>();
Entries.Add("foo");
Entries.Add("bar");
Entries.Add("#foo");
Entries.Add("1bar");
var NonAlphas = (from n in Entries
where !char.IsLetter(n.ToCharArray().First())
select n);
For Linq-to-sql you could hydrate your retrieval from the database by by enumerating the query (call ToList). From that point on, your operations will be against in-memory objects and those operations will not be translated into SQL.
List<string> Entries = dbContext.Entry.Where(n => n.EntryName).ToList();
var NonAlphas = Entries.Where(n => !char.IsLetter(n.First()));
Something like this?
List<string> lst = new List<string>();
lst.Add("first");
lst.Add("second");
lst.Add("third");
lst.Add("2abc");
var result = from i in lst where !char.IsLetter(i[0]) select i;
List<string> output = result.ToList();
Edit: I realized that using Regex here was overkill and my solution wasn't perfect anyway.
string[] x = new string[3];
x[0] = "avb";
x[1] = "31df";
x[2] = "%dfg";
var linq = from s in x where !char.IsLetter(s.ToString().First()) select s;
List<string> simplelist = new List<string>(linq);
/* in simple list you have only "31df" & "dfg" */
One thing to note is that you don't need to convert the string to a chararray to use linq on it.
The more consise version would be:
var list = new List<string> {"first","third","second","2abc"};
var result = list.Where(word => !char.IsLetter(word.First()));

Categories