How to combine multiple lists using LINQ lambda - c#

I have two lists:
list1 = [a,b,c,4]
list2 = [1,23,5,6]
Now I need to create an anonymous object using linq lambda.
Something like.
list1 = DataTable.AsEnumerable().toList();
list2 = DataTable.AsEnumerable().toList();
var result = list1.Where(x => x.Field<int>(1) == 2018).Select(x => new[] {
new {x = "XYZ", y = x[0], z = list2[0]},
....}
}
How do I go about doing this?

You need Zip Linq method, consider this example:
int[] list1 = {1, 2, 3};
string[] list2 = {"a", "b", "c"};
var result = list1.Zip(list2, (i, s) => new {y = i, z = i});

Your code is fine, it just needs some small fixes:
string [] list1 = { "a", "b", "c", "4" };
int[] list2 = { 1, 23, 5, 6 };
object[] list3 = { "test", DateTime.Now, 56 };
var result = list1.Where(x => x == "a").Select(x =>
new { x = "XYZ", y = x[0], z = list2[0], t = list3[1] }).ToList();

Related

Can i get unmatched values from two texbox like this way?

I can get values which are already matched. But i can't get unmatched values. How to make it work. Give me some advice guys
private void button13_Click(object sender, EventArgs e)
{
String a = textBox3.Text;
String b = textBox4.Text;
string test = "";
string[] titles1 = a.Split(new[] { ';', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
string[] titles2 = b.Split(new[] { ';', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
var duplicates = titles1.Distinct().Concat(titles2.Distinct()).GroupBy(title => title).Where(possibleDuplicates => possibleDuplicates.Skip(1).Any()).Select(duplicate => duplicate.First());
int i = 0;
foreach (string duplicate in duplicates)
{
//test = test + duplicate + "\r\n";
System.Data.DataTable table = new System.Data.DataTable();
table.Columns.Add("Missed call");
table.Rows.Add(duplicate);
Excel_read.DataSource = table;
}
}
This may help for you
var result = titles1.Except(titles2).Concat(titles2.Except(titles1)).ToArray();
To find the differences you may use the following code (it is written on the fly, I don't say it is an performance-optimized algorithm, it is just an idea how your problem may be solved):
var list1 = new List<int> {1, 2, 3, 5};
var list2 = new List<int> {1, 2, 4, 5, 6};
var differences = list1.Where(v => !list2.Contains(v)).Concat(
list2.Where(v => !list1.Contains(v)));
// Or this compact version:
// var differences = list1.Except(list2).Concat(list2.Except(list1));
The differences IEnumerable will will contain the following result:
{3, 4, 6}
This way:
List<string> list1 = new List<string> { "1", "2", "3", "4", "5", "7", "9"};
List<string> list2 = new List<string> { "1", "2", "3", "4", "5", "6", "8" };
List<string> list3 = list1;
list3.AddRange(list2);
list3 = list3.GroupBy(x => x).Where(x => x.Count() == 1).Select(x => x.Key).ToList();

Pairing two arrays

Suppose I have two arrays of always equal length that could look like this:
{"A", "C", "A", "A", "B", "B", "A", "A" }
{ 1, 1, 2, 3, 1, 10, 5, 7 }
Data is paired by array index.
I wish to use LINQ to produce a result that looks like below:
A: { 1, 2, 3, 5, 7 }
B: { 1, 10 }
C: { 1 }
How can I accomplish that?
The arrays come from http request parameters. The letters applies to database names and the integers are ids in a table in the database. Next step is to connect to each database and get some data for each id.
You can first Zip them, and then group them. Use the grouped result to construct a dictionary, or whatever type you want.
string[] first = { "A", "C", "A", "A", "B", "B", "A", "A" };
int[] second = { 1, 1, 2, 3, 1, 10, 5, 7 };
var list = first.Zip(second, (f, s) => new { First = f, Second = s });
Dictionary<string, int[]> d = list.GroupBy(i => i.First)
.ToDictionary(k => k.Key, v => v.Select(val => val.Second)
.ToArray()
);
Try this
string[] s = { "A", "C", "A", "A", "B", "B", "A", "A" };
int[] t = { 1, 1, 2, 3, 1, 10, 5, 7 };
var results = s.Select((x, i) => new { s = x, t = t[i] })
.GroupBy(x => x.s).ToList();

iterating over columns in a list of tuples with Linq

I have a list of List<Tuple<string[], double[]>>
List<Tuple<string[], double[]>> tt = new List<Tuple<string[], double[]>>();
var t1 = new Tuple<string[], double[]>(
new string[] { "java", "c#", "nn" },
new double[] { 2, 3, 0 });
var t2 = new Tuple<string[], double[]>(
new string[] { "java", "c#", "nn" },
new double[] { 0, 3, 1 });
var t3 = new Tuple<string[], double[]>(
new string[] { "java", "c#", "nn" },
new double[] { 2, 1, 0 });
tt.Add(t1);
tt.Add(t2);
tt.Add(t3);
Lets say I want to divide each element in the double[] by the total counts non-zero counts in the columns. I would get the following results
t1 2/2, 3/3 0/1
t2 0/2, 3/3 1/1
t3 2/2, 1/3 0/1
Here is what I tried but it counts the row totals instead of the columns
var XX = (from tuples in tt
let rows = tuples.Item2.ToArray()
let result = rows.Select(x => x/rows.Count(i => i != 0)).ToArray()
select new Tuple<string[], double[]>(tuples.Item1, result)
).ToList();
What you are trying to do can be achieved with the following LINQ query:
List<Tuple<string[], double[]>> result = tt.Select(x =>
Tuple.Create(
x.Item1,
x.Item2.Select((y, i) => y / tt.Count(z => z.Item2[i] > 0))
.ToArray())).ToList();
Here are the resultant doubles printed to console:

get common elements in lists in C#

I have two sorted lists as below:
var list1 = new List<int>() { 1, 1, 1, 2, 3 };
var list2 = new List<int>() { 1, 1, 2, 2, 4 };
I want the output to be: {1, 1, 2}
How to do this in C#?
Is there a way using Linq?
Use Intersect:
var commonElements = list1.Intersect(list2).ToList();
The extra 1 means you can't use Intersect because it returns a set.
Here's some code that does what you need:
var list1 = new List<int>() { 1, 1, 1, 2, 3 };
var list2 = new List<int>() { 1, 1, 2, 2, 4 };
var grouped1 =
from n in list1
group n by n
into g
select new {g.Key, Count = g.Count()};
var grouped2 =
from n in list2
group n by n
into g
select new {g.Key, Count = g.Count()};
var joined =
from b in grouped2
join a in grouped1 on b.Key equals a.Key
select new {b.Key, Count = Math.Min(b.Count, a.Count)};
var result = joined.SelectMany(a => Enumerable.Repeat(a.Key, a.Count));
CollectionAssert.AreEquivalent(new[] {1, 1, 2}, result);
This works nicely:
var list1 = new List<int>() { 1, 1, 1, 2, 3 };
var list2 = new List<int>() { 1, 1, 2, 2, 4 };
var lookup1 = list1.ToLookup(x => x);
var lookup2 = list2.ToLookup(x => x);
var results = lookup1.SelectMany(l1s => lookup2[l1s.Key].Zip(l1s, (l2, l1) => l1));
While both #Austin Salonen's solution and #Enigmativity's solution work for any given lists, neither take advantage of OP's condition that the lists are sorted.
Given that both lists will be ordered we can do a search in O(n + m) time where n and m are the length of each list. Not entirely sure what the previous solutions big o performance is, but it's definitely slower then O(n + m).
Basically we just walk both lists, moving one or both enumerators based on a comparison check.
var results = new List<int>();
var e1 = list1.GetEnumerator();
var e2 = list2.GetEnumerator();
var hasNext = e1.MoveNext() && e2.MoveNext();
while (hasNext) {
var value1 = e1.Current;
var value2 = e2.Current;
if (value1 == value2) {
results.Add(value1);
hasNext = e1.MoveNext() && e2.MoveNext();
} else if (value1 < value2) {
hasNext = e1.MoveNext();
} else if (value1 > value2) {
hasNext = e2.MoveNext();
}
}
That's it! results will be an empty list if no matches are found.
Note this assumes both lists are in ascending order. If it's descending, just flip the < and > operators.
I am late in answering this question, this might help future visitors.
List<int> p = new List<int> { 1, 1, 1, 2, 3 };
List<int> q = new List<int> { 1, 1, 2, 2, 4 };
List<int> x = new List<int>();
for (int i = 0; i < p.Count; i++ )
{
if (p[i] == q[i])
{
x.Add(p[i]);
}
}

Can you combine multiple lists with LINQ?

Say I have two lists:
var list1 = new int[] {1, 2, 3};
var list2 = new string[] {"a", "b", "c"};
Is it possible to write a LINQ statement that will generate the following list:
var result = new []{
new {i = 1, s = "a"},
new {i = 1, s = "b"},
new {i = 1, s = "c"},
new {i = 2, s = "a"},
new {i = 2, s = "b"},
new {i = 2, s = "c"},
new {i = 3, s = "a"},
new {i = 3, s = "b"},
new {i = 3, s = "c"}
};
?
Edit: I forgot to mention I didn't want it in query syntax. Anyway, based on preetsangha's answer I've got the following:
var result = list1.SelectMany(i => list2.Select(s => new {i = i, s = s}));
var result = from l1 in list1
from l2 in list2
select new { i = l1, s = l2};
preetsangha's answer is entirely correct, but if you don't want a query expression then it's:
var result = list1.SelectMany(l1 => list2, (l1, l2) => new { i = l1, s = l2} );
(That's what the compiler compiles the query expression into - they're identical.)

Categories

Resources