I have a list of strings and I need to select certain parts of the list to construct a separate string. What I have is:
name,gender,haircolour,car;
or
John,Male,Brown,toyota;
I also have a separate file indicating which parts, and in what order the new string should be constructed.
eg: Index = 0,3,1 would print John,toyota,Male or 1,2,0 would print Male,Brown,John.
I have tried several methods to try and select the index of the items I want, but all the functions that return values only return the contents of the List, and the only return that gives an integer is Count(), which I can't see as being helpful.
I have tried and tried but all I have succeeded in doing is confusing myself more and more. Can anyone help suggest a way to achieve this?
You should be able to do list[i], where i is the index of the element you need. There are some examples here: http://www.dotnetperls.com/list
List<string> list = new List<string> { "John", "Male", "Brown", "toyota" };
List<int> indexList = new List<int> { 0, 3, 1 };
List<string> resultList = new List<string>();
indexList.ForEach(i => resultList.Add(list[i]));
If I am understanding the question correctly, something like this should do the job:
const string data = "John,Male,Brown,toyota";
const string order = "0,3,1";
string[] indexes = order.Split(',');
string result = indexes.Aggregate("", (current, index) => current + data.Split(',')[int.Parse(index)] + ",");
result = result.TrimEnd(',');
If your string data ends with a semicolon ';', as possibly indicated in your question, then change the line to this:
string result = indexes.Aggregate("", (current, index) => current + data.Split(',')[int.Parse(index)].TrimEnd(';') + ",");
Note this solution doesn't check to make sure that the given index exists in the given data string. To add a check to make sure the index doesn't go over the array bounds, do something like this instead:
string result = indexes.Where(z => int.Parse(z) < data.Split(',').Length).Aggregate("", (current, index) => current + data.Split(',')[int.Parse(index)].TrimEnd(';') + ",");
Related
I'm fairly new to C#, and i've come across a problem trying to split on list elements.
I have a resource file containing string properties as such:
ResourceFile
ResourceFile
I've collected them in a List as:
public List<String> RawNewsList1 = new List<String>()
{
{Resource.NewsContentAndroid1},
{Resource.NewsMetaAndroid1},
};
I'm trying to split on the semicolons but only get results from my second list item.
My split look like this:
public void FilterRawNews()
{
String[] seperator = { ";;;" };
String[] filteredList1 = { "" };
for (int i = 0; i < RawNewsList1.Count; i++) {
filteredList1 = RawNewsList1[i].Split(seperator, 5,
StringSplitOptions.RemoveEmptyEntries);
}
foreach (String s in filteredList1)
{
Console.WriteLine(s);
}
}
Its only prints:
110
2.8
02-07-2020
What am i doing wrong?
Thanks in advance!
The filteredList1 variable is first filled with data from your the first resource, then at the next loop the variable's content is replaced with the data coming from the second resource.
You can use a List<string> instead that has the AddRange method to continuosly add elements to the list
List<string> filteredList1 = new List<string>();
for (int i = 0; i < RawNewsList1.Count; i++) {
filteredList1.AddRange(RawNewsList1[i].Split(seperator, 5,StringSplitOptions.RemoveEmptyEntries));
}
From this we could simplify the code to one-liner with
filteredList = RawNewsList1.SelectMany(a => a.Split(seperator,5, StringSplitOptions.RemoveEmptyEntries)).ToList();
So, what's happen in that single line? That syntax is used when you work with objects that can be treated as a sequence of data. In this context your array RawNewsList1 is a sequence of data and we can use the IEnumerable extensions brought to us by using the Linq namespace. The SelectMany extension requires a lambda expression ( a => ....) that is used to produce the instructions where each element of the sequence (a) is passed to an expression that returns another sequence of data (the array returned by Split). The sequence returned is accumulated to the sequence produced by the next elements from the original RasNewsList1. Finally the accumulated sequence is materialized with the call to ToList()
You are overwriting filteredList1 in each iteration.
That is why you only get the last result.
Just declare filteredList1 as a list and and use AddRange().
Edit: or use LINQ:
var raw = new List<string>() { "111;;;222", "333;;;444" };
String[] seperator = { ";;;" };
var filterlist1 = raw.SelectMany(r => r.Split(seperator, 5, StringSplitOptions.RemoveEmptyEntries)).ToList();
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.
This may be a sub-question to this SO Question. I want to check the string against an array of string or list.
Example
string address = "1st nice ave 1st floor";
//For now, I'm getting the list from a text file but could move to use an EF
List<string> streetType = File.ReadLines(AppDomain.CurrentDomain.BaseDirectory + #"streetType.csv")
.Where(x => x.Length > 0)
.Select(y => y.ToLowerInvariant())
.ToArray();
the purpose is to strip the extra address details after the avenue, the csv file contains all USPS accepted street type.
This is what I have now
//this only returns boolean value, I got this from the SO above
streetType.Any(testaddress.ToLower().Contains);
//I also have this
Array.Exists<string>(streetType, (Predicate<string>)delegate (string s)
{
return testaddress.IndexOf(s, StringComparison.OrdinalIgnoreCase) > -1;
});
I've been looking for hours how to resolve this then I came across the SO question which is exactly what I also want but I need to get the substring to for stripping.
If there's a linq query, that would be awesome. The only way I can think of doing this is with foreach and inner if.
Example of the array values
ave
avenue
pkwy
Update:
Here is my answer, I forgot to mention that the array lookup needs to match the exact string from the address string. I ended up using regex. This is the expanded/modified answer of #giladGreen.
var result = from item in streetTypes
let index = Regex.Match(address.ToLowerInvariant(), #"\b" + item.ToLowerInvariant() + #"\b")
where index.Success == true
select address.ToLowerInvariant().Substring(0, index.Index + item.Length);
Can somebody convert this to lambda expression? I tried I failed.
Thank you all
Use IndexOf to understand of item is present in address and if so to return the string after it:
var result = from item in streetType
let index = address.IndexOf(item)
where index != -1
select address.SubString(0, index);
One way to do this would be to simply Split each address on the streetType list, and then take the first item (at index[0]) from the resulting array:
addresses = addresses
.Select(address => address.Split(streetTypes.ToArray(), StringSplitOptions.None)[0])
.ToList();
I might be inclined to do something like this:
string[] markers = "ave avenue pkwy".Split();
string address = "1st nice ave 1st floor";
var result = markers
.Select((marker, index) => new
{
markerIndex = index,
addressPosition = address.IndexOf(marker)
})
.FirstOrDefault(x => x.addressPosition != -1);
// returns { markerIndex = 0, addressPosition = 9 }
Then result is an object that is either null (if the marker is not found) or is an object containing both markerIndex, which tells you which marker was found first, and addressPosition which tells you the character at which the marker string was found.
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}");
I have a List<string> with some 10 strings.
The values are as follows:
\\Server\Site\MySite\File1.xml
\\Server\Site\MySite\File2.xml
\\Server\Site\MySite\File2.xml
.......................
\\Server\Site\MySite\File10.xml
I need to extract \MySIte\File1.xml to \MySite\File10.xml and store in another list.
I tried to use Split keyword, with another list to populate the splitted string. But it doesn't seem to give the correct answer.
Below is the code:
for(int index=0;index<list.Count;list++)
{
string[] myArray=list[index].Split('\\');
for(int innerIndex=0;innerIndex<myArray.Length;innerIndex++)
{
anotherList[innerIndex]=myArray[2]+"\\"+myArray[3];
}
}
Experts please help.
You don't need to work too hard if you know the input of all the strings
str.Substring(str.IndexOf("\\MySite"))
One word: LINQ!
var results = (from x in source
let parts = x.Split('\\')
select String.Join("\\", parts.Skip(1)).ToArray();
You can use following code.
List<string> source = new List<string>();
source.Add(#"\\Server\Site\MySite\File1.xml");
source.Add(#"\\Server\Site\MySite\File2.xml");
source.Add(#"\\Server\Site\MySite\File2.xml");
source.Add(#"\\Server\Site\MySite\File10.xml");
foreach(string s in source)
{
string[] parts = s.Split(new string[]{ Path.DirectorySeparatorChar.ToString() },StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine(parts[parts.Length - 1] + Path.DirectorySeparatorChar +
parts[parts.Length - 2]);
}
I would just remove anything before \MySite and get the rest:
Test data used:
List<string> source = new List<string>
{
#"\\Server\Site\MySite\File1.xml",
#"\\Server\Site\MySite\File2.xml",
#"\\Server\Site\MySite\File2.xml",
#"\\Server\Site\MySite\File10.xml",
};
query:
var result =
source
// Start removing at 0 and remove everything before '\MySite'
.Select(x => x.Remove(0, x.IndexOf("\\MySite")))
.ToList();