I have 2 string arrays. The one is the base and the other is changing.
string[] baseArray = { "Gold", "Silver", "Bronze" };
string[] readArray = { "Bronze", "Silver", "Gold" };
// After comparing the readArray over the baseArray the result should be this
//string match = "Gold";
I want to get the 1st in order of the baseArray.
//Example2
string[] readArray = { "Bronze", "Silver" };
//string match should be "Silver"
If you only want one result, using LINQ:
string firstMatch = baseArray.FirstOrDefault(readArray.Contains);
If you only want one result, not using LINQ:
string firstMatch = null;
foreach(string element in baseArray)
{
if (Array.IndexOf(readArray, element) >= 0)
{
firstMatch = element;
break;
}
}
If you want all matching elements, using LINQ:
string[] common = baseArray.Intersect(readArray).ToArray();
If you want all matching elements, not using LINQ:
HasSet<string> common = new HashSet<string>(readArray);
result.Intersect(baseArray);
var match = baseArray.FirstOrDefault(x => readArray.Contains(x));
Related
I want to order list with string names by name included in brackes.
List<string> result = new List<string>();
list.ForEach(elem => result.Add(elem.Value));
result.Add(item);
result = result.OrderBy(o=>o.Split(';')[0].Substring(0, o.Length - 1).Split('(')[1]).ToList();
Example: 2-osobowy(Agrawka);Śniadanie+Obiadokolacja
I want to extract this name Agrawka
How to change instruction Substring(0, o.Length - 1)to cut last char from splitted string in orderby instruction?
If I right understood you want extract values in the brackets and sort input' list by that values. So code below sorts your data and extracts value to additional list:
List<string> resultList = new List<string>() { "2-osobowy(Bgrawka);Śniadanie+Obiadokolacja", "2-osobowy(Agrawka);Śniadanie+Obiadokolacja" };
string tempStr = null;
var extractedStr = new List<String>();
resultList = resultList.OrderBy(o =>
{
var extract = (tempStr = o.Split(';')[0].Split('(')[1]).Substring(0, tempStr.Length - 1);
extractedStr.Add(extract);
return extract;
}).ToList();
If you want only sort input data just simplify the lambda:
resultList = resultList.OrderBy(o => (tempStr = o.Split(';')[0].Split('(')[1]).Substring(0, tempStr.Length - 1)).ToList();
Below is the logic that i tried to implement and able to sort it but need to figure out to ignore special characters in it
My Logic:
Reversed string in a list
Sorted in ascending order
Again reversed back sorted strings &
Finally returned as a string by joining with ~ delimiter.
List<String> inputLst= new List<String>() { "Bananas!", "Cherry2",
"Mango","Apples", "Grape$", "Guava" };
List<String> sortList = new List<String>();
List<String> outputList = new List<String>();
foreach (String str in inputLst)
{
sortList.Add(new String(str.ToCharArray().Reverse().ToArray()));
}
sortList.Sort();
foreach (String str in sortList)
{
outputList.Add(new String(str.ToCharArray().Reverse().ToArray()));
}
Return String.Join("~", outputList);
Output i got is Bananas!~Grape$~Cherry2~Guava~Mango~Apples
Expected output should be Guava~Grape$~Mango~Bananas!~Apples~Cherry2
Could anyone please suggest me optimized solution to sort a list by last character by ignoring special characters? Here i used 2 lists for string reversals, can it be done in more efficient way?
Note: without using LINQ pls.
With a bit of LINQ and Regex, this can be achieved relatively simply:
var inputList = new List<string>() { "Bananas!", "Cherry2", "Mango","Apples", "Grape$", "Guava" };
var outputList = inputList.OrderBy(s => new string(Regex.Replace(s, "[^a-zA-Z]", "")
.Reverse()
.ToArray()))
.ToList();
var output = String.Join("~", outputList);
EDIT: Non-LINQ approach:
var inputList = new List<string>() { "Bananas!", "Cherry2", "Mango", "Apples", "Grape$", "Guava" };
inputList.Sort(new ReverseStringComparer());
var output = String.Join("~", inputList);
ReverseStringComparer:
class ReverseStringComparer : IComparer<string>
{
public int Compare(string x, string y)
{
string a = new string(Regex.Replace(x, "[^a-zA-Z]", "").Reverse().ToArray());
string b = new string(Regex.Replace(y, "[^a-zA-Z]", "").Reverse().ToArray());
return a.CompareTo(b);
}
}
Solution without regex:
string foo()
{
List<String> inputLst= new List<String>() { "Bananas!", "Cherry2", "Mango","Apples", "Grape$", "Guava" };
inputLst.Sort((l, r) => new string(l.Reverse().SkipWhile( x => !char.IsLetter(x) ).ToArray()).CompareTo( new string(r.Reverse().SkipWhile(x => !char.IsLetter(x)).ToArray()) ) );
return String.Join("~", inputLst);
}
To skip all non letter chars (and not only at the beginning of string) as suggested in comment, just use Where instead of SkipWhile like this:
string bar()
{
List<String> inputLst= new List<String>() { "Bananas!", "Cherry2", "Mango","Apples", "Grape$", "Guava" };
inputLst.Sort((l, r) => new string(l.Reverse().Where( x => char.IsLetter(x) ).ToArray()).CompareTo( new string(r.Reverse().Where(x => char.IsLetter(x)).ToArray()) ) );
return String.Join("~", inputLst);
}
Notice Where has invers logic (char.IsLetter(x)) compare to SkipWhile (!char.IsLetter(x)).
Find the last symbol being the letter and sort by it.
var inputList = new List<string>() {
"Bananas!", "Cherry2", "Mango","Apples", "Grape$", "Guava" };
var outputList = inputList.OrderBy(s => s.Last(c => char.IsLetter(c)));
Console.WriteLine(string.Join("~", outputList));
Reverse is not needed.
I have a string array like this:
string[] Array = new string[3] {"Man(21)", "Woman(33)", "Baby(4)"};
Now I want to split this array into this scheme:
Array = new string[6] {"Man", "21", "Woman", "33", "Baby", "4"};
Anybody have idea?
you can use Split and SelectMany
var result = Array.SelectMany(x => x.Split(new[]
{
'(', ')'
}, StringSplitOptions.RemoveEmptyEntries)).ToArray();
var result = from str in Array
let items = str.Split('(')
from item in items
select item.Replace(")", string.Empty);
You can give a try to regular expressions:
var pattern = #"(?<person>\w+)\((?<age>\d+)\)";
var Array = new string[3] { "Man(21)", "Woman(33)", "Baby(4)" };
Array = Array.SelectMany(item =>
{
var match = Regex.Match(item, pattern, RegexOptions.IgnoreCase);
var person = match.Groups["person"].Value;
var age = match.Groups["age"].Value;
return new List<string>{person, age};
}).ToArray();
Depending on the use case you might find it more useful to output a list of objects with Name and Age properties, or a dictionary. Here is an example of the former:
string[] arr = new[] { "Man(21)", "Woman(33)", "Baby(4)", /* test case */ "NoAge" };
var result = arr.Select(s => s.Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries)).Select(r => new
{
Name = r.First(),
Age = r.Skip(1).SingleOrDefault()
}).ToList();
The result is:
Name Age
Man 21
Woman 33
Baby 4
NoAge null
Credit to dotctor for the Split command.
How to get filename's prefix ID # into List array with RegEx? Or alternative method if you know of better one.
I only wants the 111, 222, and 333 values (ID #).
var myList = new List<string>();
myList.Add("foo/0000-0000-0001/111_Age_3_20150518T0800-0400.txt");
myList.Add("foo/0000-0000-0002/222_Bal_3_20120518T0800-0400.txt");
myList.Add("foo/0000-0000-0003/333_DDS_3_20140518T0800-0400.txt");
var filteredFiles2.Select(x => Regex.Match(x, #"^[^\d]+").Value).Distinct();
You can use the Path class to get the filename and then split it:
var filteredFiles = myList.Select(x => System.IO.Path.GetFileNameWithoutExtension(x).Split('_').First()).ToList();
Do you need the Regex function (i.e. class requirement)?
If not, you could just brute force it, like below:
private List<String> myList;
private void Init()
{
myList = new List<string>();
myList.Add("foo/0000-0000-0001/111_Age_3_20150518T0800-0400.txt");
myList.Add("foo/0000-0000-0002/222_Bal_3_20120518T0800-0400.txt");
myList.Add("foo/0000-0000-0003/333_DDS_3_20140518T0800-0400.txt");
}
private string[] filtered()
{
var list = new List<String>();
foreach (var line in myList)
{
var split1 = line.Split('/');
if (split1.Length == 3)
{
var split2 = split1[2].Split('_');
if (split2.Length == 4)
{
list.Add(split2[0]);
}
}
}
return list.ToArray();
}
Let's say I have a list of arrays with contains as below:
var listArray = new List<string[]>():
1st array = {code, ID_1, PK_1, ID_2, PK_2} //Somehow like a header
2nd array = {85734, 32343, 1, 66544, 2}
3rd array = {59382, 23324, 1, 56998, 2}
4rd array = {43234, 45334, 1, 54568, 2}
and these arrays will be added into 'listArray'.
listArray.Add(array);
what should I do for matching the variable inside the list?
e.g: if ID_1 of the array is '32343', ID_2 = '66544'.
// create
var listArray = new List<string[]>():
string whatIWantToFind = "1234";
string[] mySearchArray = new string[] {"1234", "234234", "324234"};
// fill your array here...
// search
foreach(string[] listItem in listArray)
{
// if you want to check a single item inside...
foreach(string item in listItem)
{
// you can compare
if(item == whatIWantToFind)
{
}
// or check if it contains
if(item.Contains(whatIWantToFind))
{
}
}
// to compare everything..
bool checked = true;
for(int i = 0; i < listItem.lenght; i++)
{
if(!listItem[i].Equals(mySearchArray[i])
{
checked = false; break;
}
}
// aha! this is the one
if(checked) {}
}
If you create a class that contains all the data for one array, you can make a master array of those objects. For instance:
public class ListItem {
public string code, ID_1, PK_1, ID_2, PK_2;
}
And then you can use this class:
var listArray = new List<ListItem>();
listArray.add(new ListItem(){ code = 85734, ID_1 = 32343, PK_1 = 1, ID_2 = 66544, PK_2 = 2});
listArray.add(......);
Then, to find the data, you can use a field accessor on the objects in the array:
foreach(var item in listArray)
{
if (item.ID_1.equals("32343") && item.ID_2.equals("66544"))
Console.WriteLine("Found item.");
}
var listArray = new List<string[]>
{
new []{ "code", "ID_1", "PK_1", "ID_2", "PK_2"},
new []{ "85734", "32343", "1", "66544", "2"},
new []{"59382", "23324", "1", "56998", "2"}
};
var index = listArray.First().ToList().IndexOf("ID_1");
var result = listArray.Where((a, i) => i > 0 && a[index] == "32343").ToList();