Find common characters from group of string - c#

Given the set of below strings
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
In above strings only lower case letter "r" is common in all of them.
I know we can use Intersectto find common things in 2 string but how to do using 3 strings?
This code below i did for 2 strings
var commonString = firstPartOfstring
.Intersect(secondPartOfString)
.Select(x => x)
.FirstOrDefault()
.ToString();
But cant find how to do for 3 strings

In general case you can query the strings (lines) with a help of Linq Aggregate. Please, note, that to get string from enumeration (IEnumerable<char>) we should use Concat(), not ToString():
using System.Linq;
...
// Organize the strings into a collection, say, an array
// (Set, List etc. will do as well)
string[] lines = {
"vJrwpWtwJgWrhcsFMMfFFhFp",
"jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL",
"PmmdzqPrVvPwwTWBwg",
};
...
// Query the collection above with a help of Linq:
// We turn each string into enumeration (IEnumerable<char>)
// Aggregate all enumerations into one with a help of Intersect
// Concat characters of the final enumeration to the string
string commonString = string.Concat(lines
.Select(line => line.AsEnumerable()) // we deal with IEnumerable<char>, not string
.Aggregate((s, a) => s.Intersect(a))
.OrderBy(c => c) // In case you want common characters being ordered
);
if null can appear among the strings, change .Select(...) into
.Select(line => line?.AsEnumerable() ?? Array.Empty<char>())
Please, fiddle youself.
If you want just to intersect three strings you can do it as follow:
string first = "vJrwpWtwJgWrhcsFMMfFFhFp";
string second = "jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL";
string third = "PmmdzqPrVvPwwTWBwg";
string commonString = string.Concat(first
.Intersect(second)
.Intersect(third));

Intersect is transitive -- that means you can string them together in sequence.
var commonString = firstPartOfstring
.Intersect(secondPartOfString)
.Intersect(thirdPartOfString)
.Select(x => x).FirstOrDefault().ToString();
(nb - you can sequence them in any order - the other attribute of transitive)

Related

Ordering a string with numbers in ascending order

I currently have a string that looks like this:
string numbers = "55;9;20;3";
How would i make the numbers in ascending order like this:
string numbers = "3;9;20;55";
You can try with a combination of String.Join, OrderBy and int.Parse like the following:
numbers= String.Join(";",
numbers.Split(';').OrderBy(x=> int.Parse(x)));
You can check this working example as well
You can use System.Linq namespace for this:
using System.Linq;
...
string numbers = "55;9;20;3";
string output = String.Join(",", numbers.Split(';').Select(x => int.Parse(x)).OrderBy(x => x));
I'd break this into a four step process.
// 1) Split the numbers apart using based on the delimiting character ';'
var splitString = numbers.Split(';');
// 2) Convert the array of `string` to an array of `int`
var numberArray = splitString.Select(x => int.Parse(x));
// 3) Order the array which has been output by the `Split` method.
var orderedArray = numberArray.OrderBy(x => x);
// 4) Join the string back together again in the correct order, delimited by ';'
var orderedNumbers = string.Join(";", orderedArray);
This could be squashed together into less lines of code, but by doing it in multiple stages it should give you a good understanding of what is happening.
For example, Here is the same logic in one line of code:
string orderedNumers = string.Join(";", numbers.Split(';').OrderBy(x => int.Parse(x)));

Find only equal words in list exist in string

I have several lists, with words content about 2000-3000 words:
var list1 = new List<string> {"able", "adorable", "adventurous", ...};
and than if string inputStr = "do, dream"; contains any value from list, I want, look for each word in string into string[] words = inputStr.Split(' '); foreach (string word in words) with if (list1.Any(word.Contains)).
I'm not sure, maybe it is because I use list, or my search Contains method is not correct for this case, but in result I found words, which is not equal to words exist in input string, but which contains this words as part of word, for example for word "do" or word "dream":
(do) adorable, doubt, fully, do, doh, freedom, down, double
(dream) dreamily, dream
Not sure how to avoid this, maybe better use Dictionary or SortedDictionary if problem is list. Same result I have if I check it this way var val1 = list1.FirstOrDefault(stringToCheck => stringToCheck.Contains(word)); Seems like different search gives me same results with list, all words which contains found words in input string as part of word, but desired result is to find only equal words:
(do) do
(dream) dream
IndexOf() method will get you the index of any equivalent strings within the collection.
You could also do something like this with LINQ:
list.Any(x => x == "testString");
To find the sequence that contains your "word" you should use Linq :
// (do) adorable, doubt, fully, do, doh, freedom, down, double
var result = list1.Select(word => word.Contains("do"));
But if you're trying to get word that matches fully :
var result = list1.Select(word => word.Equals("do"));
Combining this with your input list :
var result = input.SelectMany(x => list1.Where(w => w.Equals(x)));
EDIT:
Here you can check it online
You can get it done with a single Linq line:
List<string> list1 = new List<string> { "able", "adorable", "adventurous" };
string inputstr = "the adorable adventurous cat";
var found_words = inputstr.Split(' ').Where(word => list1.Contains(word));
// found_words[0] = "adorable"
// found_words[1] = "adventurous"
if (list1.Contains(word))
Will only match whole exact strings in list.
But in that case, you should make list1 a HashSet instead, that will have much better performance.
Linq is still your best bet. Assuming you want case sensitivity but don't want to observe hanging whitespace:
public string Foo(string input, List<string> list)
{
return (list.FirstOrDefault(t.Trim() == input.Trim()));
}
I personally prefer to compare strings by value than using Equals most of the time, though for string comparisons you may want to narrow down Culture as necessary..

Trying to find word in string but getting enumeration yields no result

I am having 1 long string in which i want to find word starting with Emp only after dot in my string and if match then extract that part after dot.
Below is my string:
Value.EmployeeRFID,Value.EmployeeRFID1,Value.EmkhasisGFTR,Value.EmployeeGHID,Value.EmployeeFCKJ
Now in my above input i just want to extract only part after dot(Foreg:EmployeeRFID,EmployeeRFID1 etc) and i want to add that in below list:
var list= new List<string>();
Expected output in above list variable:
[0]:EmployeeRFID ,[1]=EmployeeRFID1, [2]:EmployeeGHID, [3]:EmployeeFCKJ
This is how i am trying with linq but i am getting Enumeration yielded no results:
string str="Value.EmployeeRFID,Value.EmployeeRFID1,Value.EmkhasisGFTR,Value.EmployeeGHID,Value.EmployeeFCKJ";
var data= str.Where(t=>t.ToString().StartsWith("Emp")).Select(t=>t.t.ToString()) // Enumeration yielded no results
Try regular expressions:
string source = "Value.EmployeeRFID,...,Value.EmployeeGHID,Value.EmployeeFCKJ";
string pattern = #"(?<=\.)Emp\w*";
string[] result = Regex.Matches(source, pattern, RegexOptions.IgnoreCase)
.OfType<Match>()
.Select(match => match.Value)
.ToArray();
Test:
// EmployeeRFID
// EmployeeRFID1
// EmployeeGHID
// EmployeeFCKJ
Console.Write(string.Join(Environment.NewLine, result));
string as an argument to LINQ extensions is an IEnumerable<char>, so your t is only one character. You probably meant to do something like this:
var data= str.Split('.')
.Where(t => t.StartsWith("Emp")).Select(t => t.Split(',').First())
.ToList();
But regular expressions as suggested by Dmitry seem to be a better approach for string parsing than LINQ.

How do I get quoted fields from a delimited string as a list of unquoted values using LINQ?

Original text line is:
"125"|"Bio Methyl"|"99991"|"OPT12"|"CB"|"1"|"12"|"5"|"23"
Expected string list is free of double quotes and split by |:
125
Bio Methyl
99991
The text may contain empty quoted strings as in (former "OPT12" value now empty ""):
"125"|"Bio Methyl"|"99991"|""|"CB"|"1"|"12"|"5"|"23"
So I checked these two questions & answers :QA1 and QA2 to derive my solution.
var eList = uEList.ElementAt(i).Split(BarDelimiter);
var xList = eList.ElementAt(0).Where(char.IsDigit).ToList();
Of course it doesn't work the way I need it to be since xList is a list with elements like this: xList(0) = 1, xList(1) = 2, xList(2) = 5
I do not want to write another line to join them because this doesn't look like a suitable solution. There has to be something better with LINQ right?
How about this:
// Based on OPs comment: preserve empty non-quoted entries.
var splitOptions = StringSplitOptions.None;
//change to the below if empty entries should be removed
//var splitOptions = StringSplitOptions.None;
var line = "\"125\"|\"Bio Methyl\"|\"99991\"|\"OPT12\"|\"CB\"|\"1\"|\"12\"|\"5\"|\"23\"";
var result = line
.Split(new[] { "|" }, splitOptions)
.Select(p => p.Trim('\"'))
.ToList();
Console.WriteLine(string.Join(", ", result));
The Split(...) statement splits the input into an array with parts like
{ \"99991\", \"OPT12\", ... };
The p.Trim('\"') statement removes the leading and trailing quote from each of the parts.
As an alternative to the trimming, if there's no " in your values, you could simply sanitize the input before splitting it. You can do so by replacing the " symbol by nothing (either "" or string.Empty).
Your Split code would then give the correct result afterwards:
string uEList = "\"125\"|\"Bio Methyl\"|\"99991\"|\"OPT12\"|\"CB\"|\"1\"|\"12\"|\"5\"|\"23\"";
var eList = uEList.Replace("\"", string.Empty).Split(BarDelimiter);

How can I compare a string to a "filter" list in linq?

I'm trying to filter a collection of strings by a "filter" list... a list of bad words. The string contains a word from the list I dont want it.
I've gotten so far, the bad Word here is "frakk":
string[] filter = { "bad", "words", "frakk" };
string[] foo =
{
"this is a lol string that is allowed",
"this is another lol frakk string that is not allowed!"
};
var items = from item in foo
where (item.IndexOf( (from f in filter select f).ToString() ) == 0)
select item;
But this aint working, why?
You can use Any + Contains:
var items = foo.Where(s => !filter.Any(w => s.Contains(w)));
if you want to compare case-insensitively:
var items = foo.Where(s => !filter.Any(w => s.IndexOf(w, StringComparison.OrdinalIgnoreCase) >= 0));
Update: If you want to exlude sentences where at least one word is in the filter-list you can use String.Split() and Enumerable.Intersect:
var items = foo.Where(sentence => !sentence.Split().Intersect(filter).Any());
Enumerable.Intersect is very efficient since it uses a Set under the hood. it's more efficient to put the long sequence first. Due to Linq's deferred execution is stops on the first matching word.
( note that the "empty" Split includes other white-space characters like tab or newline )
The first problem you need to solve is breaking up the sentence into a series of words. The simplest way to do this is based on spaces
string[] words = sentence.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
From there you can use a simple LINQ expression to find the profanities
var badWords = words.Where(x => filter.Contains(x));
However this is a bit of a primitive solution. It won't handle a number of complex cases that you likely need to think about
There are many characters which qualify as a space. My solution only uses ' '
The split doesn't handle punctuations. So dog! won't be viewed as dog. Probably much better to break up words on legal characters
The reason your initial attempt didn't work is that this line:
(from f in filter select f).ToString()
evaluates to a string of the Array Iterator type name that's implied by the linq expression portion. So you're actually comparing the characters of the following string:
System.Linq.Enumerable+WhereSelectArrayIterator``2[System.String,System.String]
rather than the words of the filter when examining your phrases.

Categories

Resources