Usage of StartsWith and Contains in List<string>? - c#

I have a list.
It's possible members (x123, y123, z123, a123, b123, c123).//123 is example
This "mylist" may contain a member that starting with x, or may not. Also this is the same for y,z,a,b,c.
If contains a member starts with x:
//Formula Contains X
If Not Contains a member starts with x:
//Formula Not Contains X
//same as all of x,y,z,a,b,c. But unlike a foreach, I must place the formulas at checking time, not after.
How can I do that?

Checks if any items start with 'x' in your list:
bool result = mylist.Any(o => o.StartsWith("x"))
Checks if no items start with 'x' your list:
bool result = !mylist.Any(o => o.StartsWith("x"));

You can use .Any from Linq
bool result = mylist.Any(o => o.StartsWith("x"));
This will iterate on the list and tell you if there is at least one element that starts with "x"

public void Process(List<string> list, string key)
{
if (list.Any(i => i.StartsWith(key)))
{
//Formula Contains key
}
else
{
//Formula Not Contains key
}
}
then you can call
List<string> list = new List<string> { "x123", "y123", "z123", "a123", "b123", "c123"};
Process(list, "x");
Process(list, "a");

List<string> formula = new List<string> { "x123", "y123" };
string variable = "x";
bool containsVariable = formula.Any(s => s.StartsWith(variable));

Related

Replace the string in a list that are same with start string

I don't know if my title is correct.
I have a list
\1925\10\04\issue1
\1925\10\05\issue1
\1925\10\07\issue1
\1925\10\10\issue1
\1925\10\11\issue1
\1925\10\12\issue1
\1925\10\13\issue1
\1925\10\14\issue1
\1925\10\15\issue1
\1925\10\17\issue1
\1925\10\18\issue1
\1925\10\19\issue1
And what i want to do in the list is became
\1925\10\04\issue1
\05\issue1
\07\issue1
\10\issue1
\11\issue1
\12\issue1
\13\issue1
\14\issue1
\15\issue1
\17\issue1
\18\issue1
\19\issue1
I need it to be dynamic.
There may be instance that i have a list like this
\1925\10\04\issue1
\1925\10\04\issue2
\1925\10\04\issue3
\1925\10\04\issue4
And the output is like this
\1925\10\04\issue1
\issue2
\issue3
\issue4
So far i'm using diff match patch.
https://github.com/google/diff-match-patch/wiki/Language:-C%23
And here is my code.
diff_match_patch dmp = new diff_match_patch();
var d = dmp.diff_main(#"\1925\10\14\issue1", #"\1925\10\05\issue1");
//dmp.diff_cleanupEfficiency(d);
foreach (var item in d)
{
Console.WriteLine($"text {item.text} operation {item.operation}");
}
But is there a better way of doing this? or faster way
assuming you have the input as List<string> input then this code should work:
var splittet = input.Select(i => i.Split("\\".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
Action<string[], int> print = (string[] lst, int index) => Console.WriteLine("\\" + string.Join("\\", lst.Skip(index)));
splittet.Aggregate(new string[] { },
(common, item) =>
{
var index = Enumerable.Range(0, Math.Min(common.Length, item.Length)).FirstOrDefault(i => common[i] != item[i]);
print(item, index);
return item;
}
);
So given the input
var input = new List<string> { #"\1925\10\04\issue1",
#"\1925\10\05\issue1",
#"\1925\10\07\issue1",
#"\1925\10\10\issue1",
#"\1925\10\11\issue1",
#"\1925\10\12\issue1",
#"\1925\10\04\issue1",
#"\1925\10\04\issue2",
#"\1925\10\04\issue3",
#"\1925\10\04\issue4"};
this is the output:
\1925\10\04\issue1
\05\issue1
\07\issue1
\10\issue1
\11\issue1
\12\issue1
\04\issue1
\issue2
\issue3
\issue4
Some explanation:
First instead of working with a list of string, I split it up to a list of tokens.
Then I defined some print-action. you could instead add the result to an output-list or do whatever. In this case, it is just writing to console
then the list is aggregated. the aggreagtor starts with an empty string-array. then it tries to find the first index, where the first item differs from the emtpy list and prints all parts from this index on. and then the first index is returned to the aggregator. The aggregator then compares this first item with the second item, finds the first index where the parts differ and prints the parts from there on etc etc.

What means a combined All with Any LINQ query

I have a line of code:
bool true/false = array1.All(a => array2.Any(t => t.field == a.field));
I do not understand this combination of all + any.
Does it mean 'No field of array1 equals any field of array2' then return true ?
Would this not be the same as array1.Except(array2).Any(); ?
UPDATE
Accidently I put a "!" before the .Any() !!!
I think they are really different, it also depends on how you array is structured. If it has only field property or it has other properties as well.
Code inspection
array1.All(a => array2.Any(t => t.field == a.field));
Return true if For each element in array1 there's at least one element in array2 that has the
same value for the field property
array1.Except(array2).Any();
Return True if there's at least one element of array1 not present in
array2
Now given your context, if field is the only property of your structure it produces the same result, but it does not if there's other things going on.
For example
struct Test
{
public string int { get; set; }
public string int { get; set; }
}
//...
var array1 = new Test[]
{
new Test { Field = 0, OtherField = 1 },
new Test { Field = 1, OtherField = 2 }
}
var array2 = new Test[]
{
new Test { Field = 0, OtherField = 1 },
new Test { Field = 2, OtherField = 2 }
}
First case: is it true that for each element of array1 there's at least one element in array2 with same value in field property? False
Second case: is it true that at least one element of array1 is not present in array2? True
That means return true if there is no item in array2 which has the same value in field for all of items in array1.
Simpler version:
For all items in array1, there is no item in array2 with same value of field.
UPDATE:
Now the modified version is much simpler since it says return true if for all items in array1 there is an item in array2 with same value for field.
In summary, your first solution is to check if all the elements in array1 have the same field value in some element in array2, which could be also translated to:
var areContained =!array1.Select(e=>e.field)).Except(array2.Select(d=>d.field)).Any();
Another variant could be using a hash that could help to the efficiency if the superset if too big:
HashSet<int> hashSet = new HashSet<int>(array2.Select(d=>d.field));//Superset
bool contained = array1.Select(e=>e.field)).All(i => hashSet.Contains(i));
In your alternative you are comparing based on object instances of the arrays by using the default equality comparer, so that can produce a completely different result. Take a look the example in this link

Using List<string>.Any() to find if a string contains an item as well as find the matching item?

I have a list of strings, which can be considered 'filters'.
For example:
List<string> filters = new List<string>();
filters.Add("Apple");
filters.Add("Orange");
filters.Add("Banana");
I have another list of strings, which contains sentences.
Example:
List<string> msgList = new List<string>();
msgList.Add("This sentence contains the word Apple.");
msgList.Add("This doesn't contain any fruits.");
msgList.Add("This does. It's a banana.");
Now I want to find out which items in msgList contains a fruit. For which, I use the following code:
foreach(string msg in msgList)
{
if(filters.Any(msg.Contains))
{
// Do something.
}
}
I'm wondering, is there a way in Linq where I can use something similar to List.Any() where I can check if msgList contains a fruit, and if it does, also get the fruit which matched the inquiry. If I can get the matching index in 'filters' that should be fine. That is, for the first iteration of the loop it should return 0 (index of 'Apple'), for the second iteration return null or something like a negative value, for the third iteration it should return 2 (index of 'Banana').
I checked around in SO as well as Google but couldn't find exactly what I'm looking for.
You want FirstOrDefault instead of Any.
FirstOrDefault will return the first object that matches, if found, or the default value (usually null) if not found.
You could use the List<T>.Find method:
foreach (string msg in msgList)
{
var fruit = filters.Find(msg.Contains);
if (fruit != null)
{
// Do something.
}
}
List<string> filters = new List<string>() { "Apple", "Orange", "Banana" };
string msg = "This sentence contains the word Apple.";
var fruit = Regex.Matches(msg, #"\w+", RegexOptions.IgnoreCase)
.Cast<Match>()
.Select(x=>x.Value)
.FirstOrDefault(s => filters.Contains(s));
A possible approach to return the indexes of the elements
foreach (string msg in msgList)
{
var found = filters.Select((x, i) => new {Key = x, Idx = i})
.FirstOrDefault(x => msg.Contains(x.Key));
Console.WriteLine(found?.Idx);
}
Note also that Contains is case sensitive, so the banana string is not matched against the Banana one. If you want a case insensitive you could use IndexOf with the StringComparison operator

compare list of strings with another string

I have 1 long string which looks like :"item1, item7, item9" etc.
Then I have a list which looks like:
"item2",
"item3",
"item9"
I want to run a check to see if any of the list strings match anything within the long string. I could use a foreach loop, but I'm thinking there must be an easy LINQ expression which I can't seem to get right.
You could try something like this:
var isContained = list.Any(x=>stringValue.Contains(x));
where list is the list of strings, stringValue is the string you have.
In the above code, we use the Any method, which looks if there is any element in the list that makes the predicate we supply to be true. The predicate has as input a list item and check if this item is contained in the stringValue. If so that returns true. Otherwise false.
string longString = "item1,item7,item9";
List<string> myList=new List<string>(new string[]{"item2","item3","item9"});
if (myList.Any(str => longString.Contains(str)))
{
Console.WriteLine("success!");
}
else
{
Console.WriteLine("fail!");
}
How about:
// Set up the example data
String searchIn = "item1, item7, item9";
List<String> searchFor = new List<String>();
searchFor.Add("item2");
searchFor.Add("item3");
searchFor.Add("item9");
var firstMatch = searchFor.FirstOrDefault(p => { return -1 != searchIn.IndexOf(p); });
// firstMatch will contain null if no item from searchFor was found in searchIn,
// otherwise it will be a reference to the first item that was found.

LINQ - turn List<string> into Dictionary<string,string>

I'm just working on a Kata on my lunch and I've come unstuck...
Here's the steps I'm trying to follow:
Given an input string, split the string by the new line character
Given the string array result of the previous step, skip the first element in the array
Given the collection of strings resulting from the previous step, create a collection consisting of every 2 elements
In that last statement what I mean is, given this collection of 4 strings:
{
"string1",
"string2",
"string3",
"string4"
}
I should end up with this collection of pairs (is 'tuples' the right term?):
{
{ "string1","string2" },
{ "string3","string4" }
}
I started looking at ToDictionary, then moved over to selecting an anonymous type but I'm not sure how to say "return the next two strings as a pair".
My code looks similar to this at the time of writing:
public void myMethod() {
var splitInputString = input.Split('\n');
var dic = splitInputString.Skip(1).Select( /* each two elements */ );
}
Cheers for the help!
James
Well, you could use (untested):
var dic = splitInputStream.Zip(splitInputStream.Skip(1),
(key, value) => new { key, value })
.Where((pair, index) => index % 2 == 0)
.ToDictionary(pair => pair.key, pair => pair.value);
The Zip part will end up with:
{ "string1", "string2" }
{ "string2", "string3" }
{ "string3", "string4" }
... and the Where pair using the index will skip every other entry (which would be "value with the next key").
Of course if you really know you've got a List<string> to start with, you could just access the pairs by index, but that's boring...

Categories