I have an array which contains an elements as below
dec.02
Novemeber-2
Oct-6
.
.
.
Now suppose I want to find the index of dec.02
Suppose if an array in place of dec.02 there can be december-02.
So I want to use linq with regex which finds the index.
Date can be in any format
Regex will be (dec|december)\W*02
Can any one tell how to use regex with linq to find index from an array
Are you looking for something like that?
String[] data = new String[] {
"dec.02",
"Novemeber-2",
"Oct-6",
...
};
// All the indexes
int[] indice = data
.Select((line, index) => new {
line = line,
index = index})
.Where(item => Regex.IsMatch(item.line, "Your regular expression"))
.Select(item => item.index)
.ToArray();
In case you want 1st such index only (-1 if no index found):
// First index (or -1 if there's no such index)
int result = data
.Select((line, index) => new {
line = line,
index = index})
.Where(item => Regex.IsMatch(item.line, "Your regular expression"))
.Select(item => item.index + 1)
.FirstOrDefault() - 1;
If I understand your question correctly, this can be a solution:
Regex regex = new Regex(#"(dec|december)\W*02");
string[] dates = { "dec.02", "Novemeber-2", "Oct-6" };
int i = dates.Length - dates.SkipWhile(s => !regex.IsMatch(s)).Count(); // based-0 index
Related
Is there a way using LINQ, to find if string from one array of strings contains (partial) string from another array of strings? Something like this:
string[] fullStrings = { "full_xxx_part_name", "full_ccc_part_name", "full_zzz_part_name" };
string[] stringParts = { "a_part", "b_part", "c_part", "e_part" };
// compare fullStrings array with stringParts array
// full_ccc_part_name contains c_part (first match is OK, no need to find all)
// return index 1 (index 1 from fullStrings array)
This is asked rather for educational purpose.
I'm aware that Linq does not magically avoid the loop, instead does it in the background.
You can use Where + Any with string methods:
string[] matches = fullStrings
.Where(s => stringParts.Any(s.Contains))
.ToArray();
If you want to compare in a case insensitive way use IndexOf:
string[] matches = fullStrings
.Where(s => stringParts.Any(part => s.IndexOf(part, StringComparison.OrdinalIgnoreCase) >= 0))
.ToArray();
In case you want the indexes:
int[] matches = fullStrings
.Select((s, index) => (String: s, Index: index))
.Where(x => stringParts.Any(x.String.Contains))
.Select(x => x.Index)
.ToArray();
You would of course need to use some type of loop to find the index. Here is a solution using Linq.
This will return the first index if a match is found or -1 if none is found:
var index = fullStrings
.Select((s,i) => (s, i))
.Where(x => stringParts.Any(x.s.Contains))
.Select(x => x.i)
.DefaultIfEmpty(-1)
.First();
I will try to describe my question in the best way I can.
I have a list with X strings ("NOTION", "CATION", "COIN", "NOON").
I am trying to compare them and find the most times each character (letter) was used, use that to get the number of that character, arrange them in alphabetical order, and create a string.
So the result string should be: "ACINNOOT"
Hope is clear what I am describing.
EDIT
So far:
for (int i = 0; i < currentWord.Length; i++)
{
string letter = word.Substring(i, 1);
tempDuplicatedLetterList.Add(letter);
}
// Which letters are repeated and how many times
var duplicatedQuery = tempDuplicatedLetterList.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => new { Element = y.Key, Counter = y.Count() })
.ToList();
I came to this, although I think there might be a cleaner way to do it:
var characterSets = new string[] { "NOTION", "CATION", "COIN", "NOON" }
.SelectMany(c => c.GroupBy(cc => cc)) // create character groups for each string, and flatten the groups
.GroupBy(c => c.Key) // group the groups
.OrderBy(cg => cg.Key) // order by the character (alphabetical)
.Select(cg => new string(cg.Key, cg.Max(v => v.Count()))) // create a string for each group, using the maximum count for that character
.ToArray(); // make an array
var result = string.Concat(characterSets);
I have written a function that gives me an multidimensional array of an Match with multiple regex strings. (FileCheck[][])
FileCheck[0] // This string[] contains all the filenames
FileCheck[1] // This string[] is 0 or 1 depending on a Regex match is found.
FileCheck[2] // This string[] contains the Index of the first found Regex.
foreach (string File in InputFolder)
{
int j = 0;
FileCheck[0][k] = Path.GetFileName(File);
Console.WriteLine(FileCheck[0][k]);
foreach (Regex Filemask in Filemasks)
{
if (string.IsNullOrEmpty(FileCheck[1][k]) || FileCheck[1][k] == "0")
{
if (Filemask.IsMatch(FileCheck[0][k]))
{
FileCheck[1][k] = "1";
FileCheck[2][k] = j.ToString(); // This is the Index of the Regex thats Valid
}
else
{
FileCheck[1][k] = "0";
}
j++;
}
Console.WriteLine(FileCheck[1][k]);
}
k++;
}
Console.ReadLine();
// I need the Index of the Regex with the most valid hits
I'm trying to write a function that gives me the string of the RegexIndex that has the most duplicates.
This is what I tried but did not work :( (I only get the count of the string the the most duplicates but not the string itself)
// I need the Index of the Regex with the most valid hits
var LINQ = Enumerable.Range(0, FileCheck[0].GetLength(0))
.Where(x => FileCheck[1][x] == "1")
.GroupBy(x => FileCheck[2][x])
.OrderByDescending(x => x.Count())
.First().ToList();
Console.WriteLine(LINQ[1]);
Example Data
string[][] FileCheck = new string[3][];
FileCheck[0] = new string[]{ "1.csv", "TestValid1.txt", "TestValid2.txt", "2.xml", "TestAlsoValid.xml", "TestValid3.txt"};
FileCheck[1] = new string[]{ "0","1","1","0","1","1"};
FileCheck[2] = new string[]{ null, "3", "3", null,"1","2"};
In this example I need as result of the Linq query:
string result = "3";
With your current code, substituting 'ToList()' with 'Key' would do the trick.
var LINQ = Enumerable.Range(0, FileCheck[0].GetLength(0))
.Where(x => FileCheck[1][x] == "1")
.GroupBy(x => FileCheck[2][x])
.OrderByDescending(x => x.Count())
.First().Key;
Since the index is null for values that are not found, you could also filter out null values and skip looking at the FileCheck[1] array. For example:
var maxOccurringIndex = FileCheck[2].Where(ind => ind != null)
.GroupBy(ind=>ind)
.OrderByDescending(x => x.Count())
.First().Key;
However, just a suggestion, you can use classes instead of a nested array, e.g.:
class FileCheckInfo
{
public string File{get;set;}
public bool Match => Index.HasValue;
public int? Index{get;set;}
public override string ToString() => $"{File} [{(Match ? Index.ToString() : "no match")}]";
}
Assuming InputFolder is an enumerable of string and Filemasks an enumerable of 'Regex', an array can be filled with:
FileCheckInfo[] FileCheck = InputFolder.Select(f=>
new FileCheckInfo{
File = f,
Index = Filemasks.Select((rx,ind) => new {ind, IsMatch = rx.IsMatch(f)}).FirstOrDefault(r=>r.IsMatch)?.ind
}).ToArray();
Getting the max occurring would be much the same:
var maxOccurringIndex = FileCheck.Where(f=>f.Match).GroupBy(f=>f.Index).OrderByDescending(gr=>gr.Count()).First().Key;
edit PS, the above is all assuming you need to reuse the results, if you only have to find the maximum occurrence you're much better of with an approach such as Martin suggested!
If the goal is only to get the max occurrence, you can use:
var maxOccurringIndex = Filemasks.Select((rx,ind) => new {ind, Count = InputFolder.Count(f=>rx.IsMatch(f))})
.OrderByDescending(m=>m.Count).FirstOrDefault()?.ind;
Your question and code seems very convoluted. I am guessing that you have a list of file names and another list of file masks (regular expressions) and you want to find the file mask that matches most file names. Here is a way to do that:
var fileNames = new[] { "1.csv", "TestValid1.txt", "TestValid2.txt", "2.xml", "TestAlsoValid.xml", "TestValid3.txt" };
var fileMasks = new[] { #"\.txt$", #"\.xml$", "valid" };
var fileMaskWithMostMatches = fileMasks
.Select(
fileMask => new {
FileMask = fileMask,
FileNamesMatched = fileNames.Count(
fileName => Regex.Match(
fileName,
fileMask,
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant
)
.Success
)
}
)
.OrderByDescending(x => x.FileNamesMatched)
.First()
.FileMask;
With the sample data the value of fileMaskWithMostMatches is valid.
Note that the Regex class will do some caching of regular expressions but if you have many regular expressions it will be more effecient to create the regular expressions outside the implied fileNames.Count for-each loop to avoid recreating the same regular expression again and again (creating a regular expression may take a non-trivial amount of time depending on the complexity).
As an alternative to Martin's answer, here's a simpler version to your existing Linq query that gives the desired result;
var LINQ = FileCheck[2]
.ToLookup(x => x) // Makes a lookup table
.OrderByDescending(x => x.Count()) // Sorts by count, descending
.Select(x => x.Key) // Extract the key
.FirstOrDefault(x => x != null); // Return the first non null key
// or null if none found.
Isn't this much more easier?
string result = FileCheck[2]
.Where(x => x != null)
.GroupBy(x => x)
.OrderByDescending(x => x.Count())
.FirstOrDefault().Key;
There is a list which adds the string at runtime.
The string in the list can be like
List<string> myList=new List<string>();
0 7- 9
1 3 - 6
2 1 -3
3 10-12
Here the string contain in list does not have same pattern.
Suppose I want to find the index of 3 - 6.
So I have use an expression
3\s*\-\s*6
Now how to use it in Array.Indexof method so that I can get index of this element from mylist.
Try
myList.FindIndex(s => new Regex(#"3\s*\-\s*6").Match(s).Success);
Edit:
Working sample:
List<string> myList = new List<string>
{
"7- 9",
"3 - 6",
"1 -3",
"10-12"
};
int index = myList.FindIndex(s => new Regex(#"3\s*\-\s*6").Match(s).Success);
Console.WriteLine(index); // 1
you can do
str.Replace(" ", "");
and then you get rid of whitespace
and can just do
str.IndexOf("3-6");
Try this :
var match = Regex.Match(String.Join(String.Empty, myList.ToArray()), #"3\s*\-\s*6");
if (match.Success) {
// match.Index to get the index
// match.Value to get the value
}
You can do the same using LINQ:
var regex = new Regex(#"3\s*\-\s*6");
var index = myList.Select((x, i) => new { x, i })
.Where(x => regex.Match(x.x).Success)
.Select(x => x.i)
.First()
I have a List<bool>. I need to get the indexes of top n items where item value = true.
For example the following list items(bool)
10011001000
TopTrueIndexes(3) = The first 3 indexes where bits are true are 0, 3, 4
TopTrueIndexes(4) = The first 4 indexes where bits are true are 0, 3, 4, 7
How can I write a lambda for this?
Well, assuming you have some easily-identifiable condition, you can do something like this, which will work for any IEnumerable<T>:
var query = source.Select((value, index) => new { value, index })
.Where(x => x.value => Condition(value))
.Select(x => x.index)
.Take(n);
(Obviously fill in the appropriate bit of the Where clause. If it's just a List<bool> it may just be x => x.value.)
The important bits are that you use the overload of Select to get index/value pairs before the Where, and then another Select to get just the indexes after the Where... and use Take to only get the first n results.
There's an overload of Select where the lambda gets two parameters: the index and the element. So you can just take the indices where the value is true, supplying a sentinel (here, -1) for the ones you don't want. Then filter out the sentinels and take how many you want:
bool[] bools = ...;
var indices = bools.Select((val, ix) => val ? ix : -1).Where(i => i >= 0).Take(n);
This should probably do it.
IEnumerable<bool> GetItemsInList(IEnumerable<bool> list, int count) {
int ind = 0;
return list.Select(itm => new {i = ind++, v = itm}).Where(itm => itm.v).Take(count).Select(itm => itm.i);
}
Here how it goes:
Select source + its index
Add condition to the where clause (the source of the where clause now contains the original source + index)
Select the index (the index returned here is the original index from the original source)
var indexes = inputList.Select((input, index) => new { input, index }).Where(a => condition(a.input)).Select(a => a.index);