I have an array of strings, and I want to return an array of their lengths. Of course I could do a for loop and iterate, however I'm wondering if there's a more elegant solution, like using Linq, or some other fast/pretty one-liner.
Use the Select function to "transform" each item into another value:
var words = new[] { "some", "words", "go", "here" };
var lengths = words.Select(s => s.Length);
Using the following code:
var stringArray = new string[] {"1","12","123","1234"};
stringArray.AsParallel().ForAll(z => Console.WriteLine(z.Length));
The output should then be:
4
2
3
1
Related
This question already has answers here:
How to compare 2 List<string> objects to get the missing value from the List<string>
(5 answers)
Closed 2 years ago.
If I have two strings that are both comma separated values and I know there will only be 1 part missing from one of the strings, how can I retrieve that in C#?
Example:
String 1 = "one,two,four"
String 2 = "one,two,three,four"
Result = "three"
I've tried using String.Compare which returns -1 or 1 so I know they are different, but how do I actually pull the value of the difference?
I'd like to have a 3rd string containing the missing value from String 1
Thanks in advance.
Use linq Except both ways and union to get the differences from both.
String[] strs1 = "one,two,four".Split(",");
String[] strs2 = "one,two,three,four".Split(",");
var res = strs1.Except(strs2).Union(strs2.Except(strs1));
String result = String.Join(",",res);
string result = null;
string[] arr1 = 1.Split(','); //Get the first string into array
string[] arr2 = 2.Split(','); //Get the second string into array
//Compare lengths, if arr1 is bigger call Except on it, else on arr2
//Linq .Except will return elements of array which aren't in the parameter array
if(arr1.Length > arr2.Length
{
result = String.Join(" ", arr1.Except(arr2).ToArray());
}
else
{
result = String.Join(" ", arr2.Except(arr1).ToArray());
}
You have to convert the strings to sequences (IEnumerable<string>). Once you have that you can use Except(). The simplest way to do this is String.Split(), though I really hate the method... so many edge cases where this can fall down, and performance isn't even very good. Much better to pull in an actual CSV parser. But for brevity on Stack Overflow:
var string1 = "one,two,four";
var string2 = "one,two,three,four";
var Result = string.Join(",", string2.Split(',').Except(string1.Split(',')));
See it work here:
https://dotnetfiddle.net/l6AkOr
#Olivier Rogier already gave a good answer. Here is some code to understand the concept (his is more efficient).
var split1 = String1.Split(",");
var split 2 = String2.Split(",");
var builder = new StringBuilder();
//other ways to do this, but aiming for illustration of the concept
List<string> list1;
List<string> list2;
if(split1.Length > split2) {
list1 = split1.ToArray();
list2 = split2.ToArray();
}
else {
list2 = split1.ToArray();
list1 = split2.ToArray();
}
foreach(var s in list1)
{
if(!list2.Contains(s))
{
if(builder.Length > 0)
{
builder.Append(",");
}
builder.Append(s);
}
}
This will produce you a list of one or more items (comma separated if 2 or more). I did this freeform, so there might be a typo, so debug.
Once you understand how it works, read the comment #Olivier Rogier made to your post.
I have an array of strings like so
May#01
April#02
Jan#03
I need to sort this first alphabetically and then by the numeric value next to the #.
Alphabetical sort is obvious but I don't seem to get the numeric part.
First order strings by their values (that will give you alphabetic sort). Then filter by integer value which is after # character:
array.OrderBy(s => s)
.ThenBy(s => Int32.Parse(s.Split('#')[1]))
Sample:
string[] array = { "May#01", "April#02", "Jan#03", "April#01" };
var query = array.OrderBy(s => s)
.ThenBy(s => Int32.Parse(s.Split('#')[1]));
Result:
"April#01"
"April#02"
"Jan#03"
"May#01"
var input = new[] { "May#01", "April#02", "Jan#03", "Jan#02", "Jan#1" };
var result = input.OrderBy(s => s.Split('#')[0])
.ThenBy(s => Int32.Parse(s.Split('#')[1]));
Result:
[
"April#02",
"Jan#1",
"Jan#02",
"Jan#03",
"May#01"
]
The other answer will produce the output:
[
"April#02",
"Jan#02",
"Jan#03",
"Jan#1",
"May#01"
]
Which I'm assuming is incorrect as Jan#02 comes before Jan#1.
You could make my code more efficient by doing the split once and storing both parts in an anonymous class, along with the original string, but I don't want to convolute the code.
I have one array with names
string[] arr = { "John", "karl", "Ralf", "Florian" };
And, I have one array of lines of one file
var lines = File.ReadAllLines("test.txt");
And, inside of that column, I have some names, random names, in a specific position of the line, for example, column 10 to column 20.
How I do this now, I have an encadead loop, where I search line by line from specific name of index of first loop
for(int i=0;i<arr.Lenght;i++)
for(int j=0;j<lines.Lenght;j++)
if(lines[j].substring(10,10).trim() == arr[i].Trim())
list.Add(lines[j])
That is a very poor way, i know :(
But, I want to know, if is possible to do this using Linq, if yes, how it's possible ?
I think this should do the job
list = lines.Where(x=>arr.Contains(x.Substring(10,10).Trim()));
it will create a list from lines where line substring (10,20) is in arr
Try this:
var result = lines
.Where(line => arr.Contains(line.Substring(10, 10).Trim()))
.ToList();
Trim on arr elements is not needed - they're already trimmed. ToList can be skipped to get a lazy IEnumerable<string> or replaced with ToArray if you prefer.
LINQ, in query comprehension syntax:
var result = from line in lines
let trimmed = line.Substring(10,10).Trim()
where arr.Contains(trimmed)
select line;
NOTE: result will contain an enumeration over non-trimmed lines, which is what the OP's code originally does.
i have a list like this :
List<string> list_lines = new List<string>();
list_lines.add("name1__pass1__com__14__55");
list_lines.add("name2__pass2__com__14__5445");
list_lines.add("name3__pass3__com__14__456456");
list_lines.add("name4__pass4__com__14__1357");
list_lines.add("name5__pass5__com__14__20000");
list_lines.add("name6__pass6__com__14__25");
list_lines.add("name7__pass7__com__14__12");
and more...
as you see there is a separator here -> "__" in every string in that list.
mean :
string[] Separator = new string[] { "__" };
foreach(string s in list_lines)
{
string[] line_ar = s.Split(Separator, StringSplitOptions.None);
int Num = int.parse(line_ar[4]);
}
i want to sort that list by Num parts of that list.
i test some methods using StackOverflow, but there was a bug in them for a big list.
would be really appreciate to help me for soting it
Asc:
list_lines = list_lines.OrderBy(s => int.Parse(s.Split(Separator, StringSplitOptions.None)[4])).ToList();
Desc:
list_lines = list_lines.OrderByDescending(s => int.Parse(s.Split(Separator, StringSplitOptions.None)[4])).ToList();
var myList = list_lines.OrderBy(x => int.Parse(x.Split(new string[] {"__"}, StringSplitOptions.None)[4])).ToList();
If the number always starts after the last underscore character, then this should work:
var sortedList = list_lines
.OrderByDescending(l => int.Parse(l.Substring(l.LastIndexOf("_") + 1)))
.ToList();
The other answers create a new list which is sorted the way you want. If instead you want the same list to be sorted, maybe try something like this:
Func<string, int> getNum = str => int.Parse(str.Split(Separator, StringSplitOptions.None)[4]);
list_lines.Sort((x, y) => getNum(x).CompareTo(getNum(y)));
This uses an overload of List<>.Sort. If you want descending order, swap x and y in the Comparison<> lambda body.
If your list is very long, this is faster (uses Quick Sort) and doesn't require the memory of a new copy of the list.
You can take advantage of lambda expression in LINQ functions like OrderBy
string[] Separator = new string[] { "__" };
var sortedList = list_lines
.OrderBy(s => int.Parse(s.Split(Separator, StringSplitOptions.None)[4]))
.ToList();
As an unrelated side note, please use correct C# naming conventions so your code is easier to read and is unified with existing C# code-base. E.g. not beginning local variable names with capital letter (Separator -> separator) and using lower camel case (Pascal case) in case it contains more words (list_lines -> listLines)
Forgive me for answering a related question here:
Sat 2020-03-21 06:03:31.129: 03: [100001] Player 1
Sat 2020-03-21 06:03:33.119: 02: [620524] Player 22
I would like to first sort the list by: 1) The number within the two [] 2) The date up until the : nn:
Here's one way (of many ways) to do it:
void Main()
{
var originalList = new List<string>
{
#"Sat 2020-03-21 06:03:31.129: 03: [100001] Player 1",
#"Sat 2020-03-21 06:03:33.119: 02: [620524] Player 22",
};
var sortableList = originalList.Select(x => splitTheLine(x));
var result = sortableList.OrderBy(x => x.numberPart).ThenBy(x => x.datePart).Select(x => x.wholeString);
}
(DateTime datePart, int numberPart, string wholeString) splitTheLine(string x)
{
string[] separator = { "[", "]", ": " };
var result = x.Split(separator, StringSplitOptions.None);
return (DateTime.Parse(result[0]), int.Parse(result[3]), x );
}
I define a method splitTheLine to extract the date and number parts along with the original string. It returns a tuple. Then I use the method with the select operator of LINQ to retrieve a list with three "columns". Again with LINQ, using the OrderByand ThenByoperators I sort the list. Finally I selectonly the originial string for the result.
This solution can be shortened a lot - but at the cost of readability, as usual.
I am taking input from a text box. I've saved the input digits from text box to an array like this:
char[] _array = textBox1.Text.ToCharArray(0, textBox1.Text.Length);
Now I want to convert the array to an int array because I want to perform mathematical operations on each index of the array.
How can I achieve the goal?
Thanks.
You could do it with LINQ if you just want the character code of each char.
var intArrayOfText = "some text I wrote".ToCharArray().Select(x => (int)x);
or
var intArrayOfText = someTextBox.Text.ToCharArray().Select(x => (int)x);
If each character expected to be a digit, you can parse it to an int:
List<int> listOfInt = new List<int>();
_array.ToList().ForEach(v => listOfInt.Add(int.Parse(v.ToString())));
int[] _intArray = listOfInt.ToArray();
Character code value:
List<int> listOfCharValue = new List<int>();
_array.ToList().ForEach(v => listOfCharValue.Add((int)v));
int[] _charValueArray = listOfCharValue.ToArray();
You need to handle exceptions.
Assuming what I asked in my comment is true:
string[] ints = { "1", "2", "3" };
var str = ints.Select(i => int.Parse(i));
However, the above will work only if you have already validated that your input from the text box is numeric.
I've solved my problem. I used list to accomplish the task.
I stored each array index at the relative index of the list after converting each index value to int.
Using list seems more convenient way to me. :)
Thanks to all of you.