I’m trying to convert from this answer the code:
static IEnumerable<IEnumerable<T>> GetKCombs<T>(IEnumerable<T> list, int length) where T : IComparable
{
if (length == 1) return list.Select(t => new T[] { t });
return GetKCombs(list, length - 1)
.SelectMany(t => list.Where(o => o.CompareTo(t.Last()) > 0),
(t1, t2) => t1.Concat(new T[] { t2 }));
}
Into a list of strings. For example I want this output {1,2} {1,3} to convert it to "1,2","1,3" (this is 2 seperate string) but I cant get it. I cant even understand how I can read the results of the above function. this is my code:
int[] numbers = ListEditText.Text.Split(',').Select(x => int.Parse(x)).ToArray();
var combinations = GetKCombs(numbers, 2);
stringCombinations = combinations.Select(j => j.ToString()).Aggregate((x, y) => x + "," + y);
In the end all the results i will add them on a List with all the possible unique combinations
For example for the numbers {1,2,3} i want this List:
'1','2','3','1,2','1,3','2,3','1,2,3'
This is my code right now:
List<string> stringCombinations = new List<string>();
for (int i = 0; i < numbers.Count(); i++)
{
combinations = GetKCombs(numbers, i + 1).Select(c => string.Join(",", c));
stringCombinations.AddRange(combinations);
}
You can try first joining the results of the inner IEnumerables
var combinations = GetKCombs(numbers, 2).Select(c => string.Join(",", c));
and then concatenating them into a single string
var combinationString = string.Join("; ", combinations); // "1,2; 1,3"
Based on your edits -- if I got you right -- you can try doing
var combinationStrings =
numbers
.SelectMany((_, i) =>
GetKCombs(numbers, i + 1) // get combinations for each 'length'
.Select(c => string.Join(",", c))) // join them to a string
.ToList();
Try
var stringCombinations = string.Join(",", combinations.Select(j => $#"""{string.Join(",", j)}"""));
It prints exactly the output you want.
Related
I am trying to convert a sequence of randomly generated integers to array of strings but when I Console.WriteLine it outputs System.Char[]
public class Sorting
{
public void sortLinq(Random rand)
{
var randomValues = Enumerable.Range(1, 10).Select(_ => rand.Next(10) - 5);
var csvString = new Func<IEnumerable<int>,string>(values => {
return string.Join("," , values.Select(v => v.ToString().ToList()));
});
Console.WriteLine(csvString(randomValues.OrderBy(x=>x)));
}
}
Your problem is ) in the wrong spot.
return string.Join(",", values.Select(v => v.ToString().ToList()));
vs
return string.Join(",", values.Select(v => v.ToString()).ToList());
Even better remove .ToList completely.
return string.Join("," , values.Select(v => v.ToString()));
Having said that, there really is no need for that Func<>:
var randomValues=Enumerable.Range(1,10).Select(_ => rand.Next(10) - 5)
.OrderBy(x => x);
var s = string.Join(",", randomValues.Select( i => i.ToString()));
Console.WriteLine(s);
How can I get the first indexes from my list of lists and get it's average value. Currently I have return value on my list:
[["1.11, 2.11, 3.11"], ["2.11, 3.11, 4.11"], ["4.11, 5.11, 6.11"]]
Here is my expected result:
var index0 = 2.44
var index1 = 3.44
var index2 = 4.44
On single list only I am using this to get the average:
var avg = myList.Select(double.Parse).Average();
Any suggestion/comments TIA.
Edit Solution because you edited.
String[][] TValue = new String[][]
{
new String[] {"1.11", "2.11", "3.11" },
new String[] {"2.11", "3.11", "4.11" },
new String[] {"4.11", "5.11", "6.11" }
};
Console.WriteLine("Avg[0] => {0:F2}", TValue.Select(x => double.Parse(x[0])).Average());
Console.WriteLine("Avg[1] => {0:F2}", TValue.Select(x => double.Parse(x[1])).Average());
Console.WriteLine("Avg[2] => {0:F2}", TValue.Select(x => double.Parse(x[2])).Average());
this is what you expected.
hope this work.
It seems that you need to get avg based on columns index instead of rows then .Zip will be one option for you,
Suppose your list of list of string is,
var myList = new List<List<string>>
{
new List<string> { "1.11, 2.11, 3.11" }, //<= Notice here single item in list with comma(,) separated
new List<string> { "2.11, 3.11, 4.11" },
new List<string> { "4.11, 5.11, 6.11" }
};
So you need to first split your string in inner list with comma(,) to get each item as separate string,
var list = myList
.SelectMany(x => x
.Select(y => y.Split(',')
.Select(z => z.Trim())
.ToList()))
.ToList();
Then you can make .Zip on all above 3 list by
var results = list[0]
.Zip(list[1], (a, b) => double.Parse(a) + double.Parse(b))
.Zip(list[2], (x, y) => (x + double.Parse(y)) / 3)
.ToList();
//------------------Print the result---------------
foreach (var item in results)
{
Console.WriteLine(Math.Round(item, 2));
}
How .Zip works?
Lets take all columns value on index 0.
a = "1.11"
b = "2.11"
Then 1st Zip result will be =>
double.Parse(a) + double.Parse(b)
= 1.11 + 2.11
= 3.22
So for 2nd .Zip the x now be the result of the above 1st .Zip that means
x = 3.22
y = "4.11"
Then 2nd Zip result will be =>
(x + double.Parse(y)) / 3
= (3.22 + 4.11) / 3
= 2.44
So for Average of your values at column index 0 => 2.44
In above,
list[0] : 1st list in your list of list of string.
list[1] : 2nd list in your list of list of string.
list[2] : 3rd list in your list of list of string.
Output: (From Console)
You can zip all three lists
using zipThree from How to combine more than two generic lists in C# Zip?
using System;
using System.Collections.Generic;
using System.Linq;
public static class MyFunkyExtensions
{
public static IEnumerable<TResult> ZipThree<T1, T2, T3, TResult>(
this IEnumerable<T1> source,
IEnumerable<T2> second,
IEnumerable<T3> third,
Func<T1, T2, T3, TResult> func)
{
using (var e1 = source.GetEnumerator())
using (var e2 = second.GetEnumerator())
using (var e3 = third.GetEnumerator())
{
while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext())
yield return func(e1.Current, e2.Current, e3.Current);
}
}
}
class MainClass {
public static void Main (string[] args) {
var list = new List<List<double>> { new List<double> {1.11,2.11,3.11}, new List<double> {2.11,3.11,4.11}, new List<double> {4.11,5.11,6.11} };
var a = list[0].ZipThree(list[1], list[2], (x, y, z) => (x + y + z) / 3);
Console.WriteLine(
string.Join(",",
a.Select(s => s.ToString())));
}
}
And it returns
2.44333, 3.443333, 4.44333
I'm assuming all the inner lists have the same length, and you want to count the average of the corresponding indices (i.e. index0 is average of 0th value from each list, index1 is average of the 1st value etc.).
In such case to obtain the averages for each index you use the following code:
int listLength = myList.First().Length; // Length for an array
// Count for a List<T>
var averages = Enumerable.Range(0, listLength).Select(
index => myList.Average(innerList => double.Parse(innerList[index]))
).ToList();
You could do so using Linq.
Updated based on comment
var list = new [] { "1.11, 2.11, 3.11" , "2.11,3.11, 4.11" , "4.11,5.11,6.11" };
var collection = list.Select(x => x.Split(',').Select(c => double.Parse(c)).ToList()).ToList();
var result = collection.First()
.Select((dummy, i) =>
collection.Average(inner => inner[i]));
Output
2.44
3.44
4.44
There is a int[] array that stores different numbers.
What I want is to group the indexes of those same numbers in the array to the same groups.
For exmaple, the array is int[5]{1,2,5,1,5}
I would like to see the output is List<List<int>> { {0,3}, {1}, {2,4} } // don't mind syntax
It's better if Linq (or a more efficient way) can be used, thanks for help.
You can simply use GroupBy and the position obtained from the Select overload:
int[] array;
var result = array.Select((v, idx) => new { Value = v, Index = idx })
.GroupBy(g => g.Value)
.Select(g => g.ToArray()) // inner array
.ToArray(); // outer array
One of ways:
var result = myArray.Select((elem, idx) => new { Value = elem, Idx = idx})
.GroupBy(proxy => proxy.Value);
foreach (var grouped in result)
{
Console.WriteLine("Element {0} has indexes: {1}",
grouped.Key,
string.Join(", ", grouped.Select(proxy => proxy.Idx).ToArray()));
}
var myFinalList = result.Select(proxy => proxy.ToArray()).ToList();
You can use Enumerable.Range combined with GroupBy:
int[] arr = { 1, 2, 5, 1, 5 };
var result = Enumerable.Range(0, arr.Length)
.GroupBy(i => arr[i])
.Select(x => x.ToList()).ToList();
DEMO HERE
Say I have an array like this
string [] fruits = {"watermelon","apple","apple","kiwi","pear","banana"};
Is there an built in function that allows me to query all the index of "apple" ?
For example,
fruits.FindAllIndex("apple");
will return an array of 1 and 2
If there is not, how should I implement it?
Thanks!
LINQ version:
var indexes = fruits.Select((value, index) => new { value, index })
.Where(x => x.value == "apple")
.Select(x => x.index)
.ToList();
Non-LINQ version, using Array<T>.IndexOf() static method:
var indexes = new List<int>();
var lastIndex = 0;
while ((lastIndex = Array.IndexOf(fruits, "apple", lastIndex)) != -1)
{
indexes.Add(lastIndex);
lastIndex++;
}
One way would be to write like this:
var indices = fruits
.Select ((f, i) => new {f, i})
.Where (x => x.f == "apple")
.Select (x => x.i);
Or the traditional way:
var indices = new List<int>();
for (int i = 0; i < fruits.Length; i++)
if(fruits[i] == "apple")
indices.Add(i);
Pretty easy with an extension method.
var fruits = new[] { "watermelon","apple","apple","kiwi","pear","banana" };
var indexes = fruits.FindAllIndexes("apple");
public static class Extensions
{
public static int[] FindAllIndexes(this string[] array, string search) => array
.Select((x, i) => (x, i))
.Where(value => value.x == search)
.Select(value => value.i)
.ToArray();
}
I have a string array[2] as follows:
1st Array 2nd Aray
"100101" "Testing123"
"100102" "Apple123"
"100101" "Dog123"
"100104" "Cat123"
"100101" "Animal123"
I would like to concatenate all elements of the 2nd array if the elements in the first array match.
For example elements of the first array that match are "100101", "100101" and "100101". So a string with the concatenated values of the respective 2nd array would be as follows:
"Testing123 Dog123 Animal123"
How could this be achieved elegantly?
I did it this way:
var results =
array1
.Zip(array2, (x1, x2) => new { x1, x2 })
.ToLookup(x => x.x1, x => x.x2)
.Select(x => new { x.Key, Value = String.Join(" ", x), });
I got this result:
If you needed to extract the results in a different way it wouldn't be too hard to fiddle with my method to get what you need.
You can use GroupBy:
var strings = array1.Select((s,index) => new{ s, index })
.GroupBy(x => x.s)
.Select(g =>
string.Join(" ", g.Select(x => array2.ElementAtOrDefault(x.index))));
foreach(string s in strings)
Console.WriteLine(s);
If you want to concatenate only strings which are duplicates in the first array, add this Where:
// ...
.GroupBy(x => x.s)
.Where(g => g.Count() > 1)
// ...
Here's a Demo
var indices = array1.Select((i, s) => new {Index = i, Str = s})
.Where(e => e.Str == "100101")
.Select(e => e.Index);
string result = string.Join(" ", array2.Select((i, s) => new {Index = i, Str = s})
.Where(e => indices.Contains(e.Index))
.Select(e => e.Str));
assuming both arrays are the same length, this should give you the output you need.
var array1 = new[] {"100101", "100102", "100101", "100104","100101" };
var array2 = new[] { "Testing123", "Apple123", "Dog123","Cat123", "Animal123" };
var result = new Dictionary<string, string>();
for (int i = 0; i < array1.Length; i++)
{
// if the value has been found before
if( result.ContainsKey( array1[i] ) ) {
result[array1[i]] += " " + array2[i]; // append to existing "matched" entry
}
else {
result.Add(array1[i], array2[i]); // add new unique value
}
}
You can zip these two arrays as they are of same size. Then group the elements by first array value.
Then join the elements.
I wrote a sample program using linq
string[] array1 = new string[]{"100101","100102","100101","100104","100101"};
string[] array2 = new string[] { "Testing123", "Apple123", "Dog123", "Cat123", "Animal123" };
var concatenatedString = array1.Zip(array2, (x, y) => new { First = x, Second = y }).GroupBy(t => t.First).Select(t=> string.Join(" ",t.Select(s=> s.Second))).ToList();
The result will contain a list of concatenated strings.
Hope it Helps
var arr1 = new [] { "100101", "100102", "100101", "100104", "100101" };
var arr2 = new [] { "Testing123", "Apple123", "Dog123", "Cat123", "Animal123" };
var result = string.Join(" ", arr2.Where((a, i) => i < arr1.Length && arr1[i] == "100101"));