Dynamically concatenate value in list if pattern matched - c#

I have a list of string and an array of pattern
List<string> filePaths = Directory.GetFiles(dir, filter).ToList();
string[] prefixes = { "0.", "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9." };
I want to replace value in filePaths for example like this:
"1. fileA" becomes "01. fileA"
"2. fileB" becomes "02. fileB"
"10. fileC" becomes "10. fileC" (since "10." is not in prefixes list)
Is there a way to do this without looping?

You can do the following, using Select:
class Program
{
static void Main(string[] args)
{
string[] prefixes = { "0.", "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9." };
var result = Directory.GetFiles(dir, filter).Select(s => prefixes.Contains(s.Substring(0, 2)) ? "0" + s : s).ToList();
}
}
You enumerate the enumerable to check for the condition whether padding is needed, if so you pad, otherwise just return the original value.

No need for a prefixes list, you can just pad left with 0's using regex:
string input = "1. fileA";
string result = Regex.Replace(input, #"^\d+", m => m.Value.PadLeft(2, '0'));
To use on the whole list:
var filePaths = Directory.GetFiles(dir, filter).Select(s => Regex.Replace(s, #"^\d+", m => m.Value.PadLeft(2, '0'))).ToList();

Related

Read text from a text file with specific pattern

Hi there I have a requirement where i need to read content from a text file. The sample text content is as below.
Name=Check_Amt
Public=Yes
DateName=pp
Name=DBO
I need to read the text and only extract the value which comes after Name='What ever text'.
So I am expecting the output as Check_Amt, DBO
I need to do this in C#
When querying data (e.g. file lines) Linq is often a convenient tool; if the file has lines in
name=value
format, you can query it like this
Read file lines
Split each line into name, value pair
Filter pairs by their names
Extract value from each pair
Materialize values into a collection
Code:
using System.Linq;
...
// string[] {"Check_Amt", "DBO"}
var values = File
.ReadLines(#"c:\MyFile.txt")
.Select(line => line.Split(new char[] { '=' }, 2)) // split into name, value pairs
.Where(items => items.Length == 2) // to be on the safe side
.Where(items => items[0] == "Name") // name == "Name" only
.Select(items => items[1]) // value from name=value
.ToArray(); // let's have an array
finally, if you want comma separated string, Join the values:
// "Check_Amt,DBO"
string result = string.Join(",", values);
Another way:
var str = #"Name=Check_Amt
Public=Yes
DateName=pp
Name=DBO";
var find = "Name=";
var result = new List<string>();
using (var reader = new StringReader(str)) //Change to StreamReader to read from file
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.StartsWith(find))
result.Add(line.Substring(find.Length));
}
}
You can use LINQ to select what you need:
var names=File. ReadLines("my file.txt" ).Select(l=>l.Split('=')).Where(t=>t.Length==2).Where(t=>t[0]=="Name").Select(t=>t[1])
I think that the best case would be a regex.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = #"(?<=Name=).*?(?=Public)";
string input = #"Name=Check_Amt Public=Yes DateName=pp Name=DBO";
RegexOptions options = RegexOptions.Multiline;
foreach (Match m in Regex.Matches(input, pattern, options))
{
Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
}
}
}
EDIT: My answer was written before your question were corrected, while it's still working the LINQ answer would be better IMHO.

Check if a particular string is contained in a list of strings

I'm trying to search a string to see if it contains any strings from a list,
var s = driver.FindElement(By.Id("list"));
var innerHtml = s.GetAttribute("innerHTML");
innerHtml is the string I want to search for a list of strings provided by me, example
var list = new List<string> { "One", "Two", "Three" };
so if say innerHtml contains "One" output Match: One
You can do this in the following way:
int result = list.IndexOf(innerHTML);
It will return the index of the item with which there is a match, else if not found it would return -1.
If you want a string output, as mentioned in the question, you may do something like:
if (result != -1)
Console.WriteLine(list[result] + " matched.");
else
Console.WriteLine("No match found");
Another simple way to do this is:
string matchedElement = list.Find(x => x.Equals(innerHTML));
This would return the matched element if there is a match, otherwise it would return a null.
See docs for more details.
You can do it with LINQ by applying Contains to innerHtml for each of the items on the list:
var matches = list.Where(item => innerHtml.Contains(item)).ToList();
Variable matches would contain a subset of strings from the list which are matched inside innerHtml.
Note: This approach does not match at word boundaries, which means that you would find a match of "One" when innerHtml contains "Onerous".
foreach(var str in list)
{
if (innerHtml.Contains(str))
{
// match found, do your stuff.
}
}
String.Contains documentation
For those who want to serach Arrray of chars in another list of strings
List WildCard = new() { "", "%", "?" };
List PlateNo = new() { "13eer", "rt4444", "45566" };
if (WildCard.Any(x => PlateNo.Any(y => y.Contains(x))))
Console.WriteLine("Plate has wildchar}");

Get the Substrings within the List<string> collection using Linq

I've a collection list.
List<string> mycollections = new List<string>(new string[]
{
"MyImages/Temp/bus.jpg",
"MyImages/Temp/car.jpg",
"MyImages/Temp/truck.jpg",
"MyImages/Temp/plane.jpg",
"MyImages/Temp/ship.jpg",
});
I required only files in a List such asbus.jpg, car.jpg...... Here i do not need "MyImages/Temp/" portion of the string in the same list.
I tried with Substring and Split with Linq queries but couldn't get the expected result.
Use Path.GetFileName instead of substring like:
var fileNames = mycollections.Select(r => Path.GetFileName(r)).ToList();
For output:
var fileNames = mycollections.Select(r => Path.GetFileName(r));
foreach (var item in fileNames)
{
Console.WriteLine(item);
}
Output:
bus.jpg
car.jpg
truck.jpg
plane.jpg
ship.jpg
How about this:
mycollections.Select(s => s.Split('/').Last());
That will split each string by slashes and return the last item.

Convert a list of strings to a single string

List<string> MyList = (List<string>)Session["MyList"];
MyList contains values like: 12 34 55 23.
I tried using the code below, however the values disappear.
string Something = Convert.ToString(MyList);
I also need each value to be separated with a comma (",").
How can I convert List<string> Mylist to string?
string Something = string.Join(",", MyList);
Try this code:
var list = new List<string> {"12", "13", "14"};
var result = string.Join(",", list);
Console.WriteLine(result);
The result is: "12,13,14"
Entirely alternatively you can use LINQ, and do as following:
string finalString = collection.Aggregate("", (current, s) => current + (s + ","));
However, for pure readability, I suggest using either the loop version, or the string.Join mechanism.
Or, if you're concerned about performance, you could use a loop,
var myList = new List<string> { "11", "22", "33" };
var myString = "";
var sb = new System.Text.StringBuilder();
foreach (string s in myList)
{
sb.Append(s).Append(",");
}
myString = sb.Remove(sb.Length - 1, 1).ToString(); // Removes last ","
This Benchmark shows that using the above loop is ~16% faster than String.Join() (averaged over 3 runs).
You can make an extension method for this, so it will be also more readable:
public static class GenericListExtensions
{
public static string ToString<T>(this IList<T> list)
{
return string.Join(",", list);
}
}
And then you can:
string Something = MyList.ToString<string>();
I had to add an extra bit over the accepted answer. Without it, Unity threw this error:
cannot convert `System.Collections.Generic.List<string>' expression to type `string[]'
The solution was to use .ToArray()
List<int> stringNums = new List<string>();
String.Join(",", stringNums.ToArray())

extracting the common prefixes from a list of strings

I have a list of strings, such as:
{ abc001, abc002, abc003, cdef001, cdef002, cdef004, ghi002, ghi001 }
I want to get all the common unique prefixes; for example, for the above list:
{ abc, cdef, ghi }
How do I do that?
var list = new List<String> {
"abc001", "abc002", "abc003", "cdef001",
"cdef002", "cdef004", "ghi002", "ghi001"
};
var prefixes = list.Select(x = >Regex.Match(x, #"^[^\d]+").Value).Distinct();
It may be a good idea to write a helper class to represent your data. For example:
public class PrefixedNumber
{
private static Regex parser = new Regex(#"^(\p{L}+)(\d+)$");
public PrefixedNumber(string source) // you may want a static Parse method.
{
Match parsed = parser.Match(source); // think about an error here when it doesn't match
Prefix = parsed.Groups[1].Value;
Index = parsed.Groups[2].Value;
}
public string Prefix { get; set; }
public string Index { get; set; }
}
You need to come up with a better name, of course, and better access modifiers.
Now the task is quite easy:
List<string> data = new List<string> { "abc001", "abc002", "abc003", "cdef001",
"cdef002", "cdef004", "ghi002", "ghi001" };
var groups = data.Select(str => new PrefixedNumber(str))
.GroupBy(prefixed => prefixed.Prefix);
The result is all data, parsed, and grouped by the prefix.
You can achieve that using Regular Expression to select the text part, and then use HashSet<string> to add that text part so no duplication added:
using System.Text.RegularExpressions;
//simulate your real list
List<string> myList = new List<string>(new string[] { "abc001", "abc002", "cdef001" });
string pattern = #"^(\D*)\d+$";
// \D* any non digit characters, and \d+ means followed by at least one digit,
// Note if you want also to capture string like "abc" alone without followed by numbers
// then the pattern will be "^(\D*)$"
Regex regex = new Regex(pattern);
HashSet<string> matchesStrings = new HashSet<string>();
foreach (string item in myList)
{
var match = regex.Match(item);
if (match.Groups.Count > 1)
{
matchesString.Add(match.Groups[1].Value);
}
}
result:
abc, cde
Assuming that your prefix is all alpha characters and terminited by the first non-alpha character, you could use the following LINQ expression
List<string> listOfStrings = new List<String>()
{ "abc001d", "abc002", "abc003", "cdef001", "cdef002", "cdef004", "ghi002", "ghi001" };
var prefixes = (from s in listOfStrings
select new string(s.TakeWhile(c => char.IsLetter(c)).ToArray())).Distinct();

Categories