Linq with multiple foreach inserting items to table - c#

I have list of ids like this below
List<int> ids = new List<int>();
and then i have list of lengths which is also integers like this below..
List<int> lengths = new List<int>();
now i need to insert into table using linq query with the data format like this below
ID length
1 1
1 2
1 3
2 1
2 2
2 3
for that i am doing like this
foreach (var item in ids)
{
foreach (var item in lengths)
{
}
}
With the above way i am not able insert the multiple id's in the table .. I am hoping there should be better way to do this..
Could any one please suggest any ideas on this one that would be very grateful to me..
Thanks in advance.

If you wanted to project these 2 lists to a flattened list with LINQ, you could use SelectMany
Projects each element of a sequence to an IEnumerable and flattens
the resulting sequences into one sequence.
// projecting to an anonymous type
var results = ids.SelectMany(id => lengths.Select(length => new {id, length }));
// or projecting to a value tuple
var results = ids.SelectMany(id => lengths.Select(length => (id, length)));

If you really want a single loop, you can loop over the final result length and compute the indexes into each List:
var idsCount = ids.Count;
var lengthsCount = lengths.Count;
var totalCount = idsCount * lengthsCount;
for (int j1 = 0; j1 < totalCount; ++j1) {
var id = ids[j1 / lengthsCount];
var length = lengths[j1 % lengthsCount];
new { id, length }.Dump();
// insert id,length
}

Related

List sort according to desired condition

var non_community1 =new List<string>{ "red-11","red-10","red-9","orange-11","green-11","green-7","green-9", "green-9" ,"orange-9","green-11"};
non_community1 = non_community1.OrderByDescending(s => int.Parse(Regex.Match(s, #"\d+").Value)).ToList();
for (int i = non_community1.Count - 1; i > 0; i--)
{
if ((non_community1[i] == non_community1[i - 1]))
{
non_community1.RemoveAt(i);
}
}
this code give me that to sort
this is the list i want to produce
I'm a little stuck at this part, how do I get out of it?
I want to write the same at least 3 numbers in different color groups in sequence and I want to add "null" between the numbers that write 3 or more consecutive numbers.
ok so (after you removed the duplicates) you would need to use GroupBy to aggregate the items with the same integer and sort them according to their occurence:
var groupedResult = non_community1
.GroupBy( s => int.Parse(Regex.Match(s, #"\d+").Value))
.OrderByDescending(k => k.Count()).ToList();
Now you need to go through each group and collect them in the final list.
and I want to add "null" between the numbers that write 3 or more consecutive numbers.
For this you can check how many items are in each group if you have more than 2 items then add the null item.
List<string> finalList = new List<string>();
for ( int i = 0; i < groupedResult.Count; i++ )
{
finalList.AddRange(groupedResult[i]);
if(groupedResult[i].Count() > 2)
{
finalList.Add(null);
}
}
Console.WriteLine(string.Join(Environment.NewLine, finalList));
and you should have your desired result

SELECT SQLite.NET records where IDs match int array

I am using SQLite.NET. I am trying to pass an integer array to a search query. I would like to return a list of records where the IDs (table attributes) match the integers in an array. The array is of size 10.
In MainPage.cs:
int[] arr = new int[10];
// for testing purposes
for (int i = 0; i <= 9; i++{
arr[i] = i;
}
var selected = App.Database.SearchList(arr);
In SQLiteDatabase.cs:
public List<Rooms> SearchList(int[] ID)
{
return database.Query<Rooms>("SELECT * FROM Rooms WHERE ID = ?;", ID);
}
This results in the following error when the query is executed:
System.NotSupportedException: Timeout exceeded getting exception details
How can I return a list of records where the IDs match? Thank you.
use the IN keyword
WHERE ID IN (1, 2, 3, 4, 5)
Apparently SQLite.NET does not support passing in an array as a parameter.
This throws and exception:
var IDs = new[] { 1, 2 };
return database.Query<Rooms>("SELECT * FROM Rooms WHERE ID IN (?);", IDs);
In this case the only solution is to join the paramters in the SQL string. This works for int[], but when using strings you should beware of SQL injection.
var IDs = new[] { 1, 2 };
return database.Query<Rooms>($"SELECT * FROM Rooms WHERE ID IN ({string.Join(",", IDs)});");
You need to have 1 '?' per argument so you can create your query string like this:
string query = $"SELECT * FROM Rooms WHERE ID IN ({string.Join(",", IDs.Select(x => "?"))});"
This makes the IN clause like (?,?,...,?)
Then when calling Query its necessary to cast the arguments to an object array or you'll get the exception as mentioned by #Neil B like this:
return database.Query<Rooms>(query,IDs.Cast<object>().ToArray());

How to create new list from list of list where elements are in new list are in alternative order? [duplicate]

This question already has answers here:
Interleaving multiple (more than 2) irregular lists using LINQ
(5 answers)
Closed 5 years ago.
Suppose I have list of list. I want to create new list from given list of list such that elements are in order of example given below.
Inputs:-
List<List<int>> l = new List<List<int>>();
List<int> a = new List<int>();
a.Add(1);
a.Add(2);
a.Add(3);
a.Add(4);
List<int> b = new List<int>();
b.Add(11);
b.Add(12);
b.Add(13);
b.Add(14);
b.Add(15);
b.Add(16);
b.Add(17);
b.Add(18);
l.Add(a);
l.Add(b);
Output(list):-
1
11
2
12
3
13
4
14
15
16
And output list must not contain more than 10 elements.
I am currently doing this using foreach inside while but I want to know how can I do this using LINQ.
int loopCounter = 0,index=0;
List<int> o=new List<int>();
while(o.Count<10)
{
foreach(List<int> x in l)
{
if(o.Count<10)
o.Add(x[index]);
}
index++;
}
Thanks.
Use the SelectMany and Select overloads that receive the item's index. That will be used to apply the desired ordering. The use of the SelectMany is to flatten the nested collections level. Last, apply Take to retrieve only the desired number of items:
var result = l.SelectMany((nested, index) =>
nested.Select((item, nestedIndex) => (index, nestedIndex, item)))
.OrderBy(i => i.nestedIndex)
.ThenBy(i => i.index)
.Select(i => i.item)
.Take(10);
Or in query syntax:
var result = (from c in l.Select((nestedCollection, index) => (nestedCollection, index))
from i in c.nestedCollection.Select((item, index) => (item, index))
orderby i.index, c.index
select i.item).Take(10);
If using a C# 6.0 and prior project an anonymous type instead:
var result = l.SelectMany((nested, index) =>
nested.Select((item, nestedIndex) => new {index, nestedIndex, item}))
.OrderBy(i => i.nestedIndex)
.ThenBy(i => i.index)
.Select(i => i.item)
.Take(10);
To explain why Zip alone is not enough: zip is equivalent to performing a join operation on the second collection to the first, where the
attribute to join by is the index. Therefore Only items that exist in the first collection, if they have a match in the second, will appear in the result.
The next option is to think about left join which will return all items of the first collection with a match (if exists) in the second. In the case described OP is looking for the functionality of a full outer join - get all items of both collection and match when possible.
I know you asked for LINQ, but I do often feel that LINQ is a hammer and as soon as a developer finds it, every problem is a nail. I wouldn't have done this one with LINQ, for a readability/maintainability point of view because I think something like this is simpler and easier to understand/more self documenting:
List<int> r = new List<int>(10);
for(int i = 0; i < 10; i++){
if(i < a.Count)
r.Add(a[i]);
if(i < b.Count)
r.Add(b[i]);
}
You don't need to stop the loop early if a and b collectively only have eg 8 items, but you could by extending the test of the for loop
I also think this case may be more performant than LINQ because it's doing a lot less
If your mandate to use LINQ is academic (this is a homework that must use LINQ) then go ahead, but if it's a normal everyday system that some other poor sucker will have to maintain one day, I implore you to consider whether this is a good application for LINQ
This will handle 2 or more internal List<List<int>>'s - it returns an IEnumerable<int> via yield so you have to call .ToList() on it to make it a list. Linq.Any is used for the break criteria.
Will throw on any list being null. Add checks to your liking.
static IEnumerable<int> FlattenZip (List<List<int>> ienum, int maxLength = int.MaxValue)
{
int done = 0;
int index = 0;
int yielded = 0;
while (yielded <= maxLength && ienum.Any (list => index < list.Count))
foreach (var l in ienum)
{
done++;
if (index < l.Count)
{
// this list is big enough, we will take one out
yielded++;
yield return l[index];
}
if (yielded > maxLength)
break; // we are done
if (done % (ienum.Count) == 0)
index += 1; // checked all lists, advancing index
}
}
public static void Main ()
{
// other testcases to consider:
// in total too few elememts
// one list empty (but not null)
// too many lists (11 for 10 elements)
var l1 = new List<int> { 1, 2, 3, 4 };
var l2 = new List<int> { 11, 12, 13, 14, 15, 16 };
var l3 = new List<int> { 21, 22, 23, 24, 25, 26 };
var l = new List<List<int>> { l1, l2, l3 };
var zipped = FlattenZip (l, 10);
Console.WriteLine (string.Join (", ", zipped));
Console.ReadLine ();
}

Using a nested foreach to store one foreach value into an array

Alright so I didn't really know how to word this question, but I did my best. The goal I am trying to accomplish is to go through categories using a foreach loop. Inside the category foreach loop another foreach loop will go through Numbers. Right now it is grabbing ever value in the tables and storing them into an array. My goal is to only store the highest number in each category into the array.
Here is how the tables would look:
Category Table
Title NumberId
Type 1
Priority 2
Likelihood 3
Numbers Table
Order NumberId
3 1
2 1
1 1
3 2
2 2
1 2
3 3
2 3
1 3
So my goal would be instead of storing every order value into the array. I would like to store the highest number according to each number id. So there array would include 3,3,3.
This is what I have that stores every number into an array:
int[] values = new int[count];
foreach(var x in Category)
{
foreach(var w in x.Numbers)
{
values[y] = w.Order;
y++;
}
}
Solution:
int[] values = new int[count];
foreach(var x in Category)
{
foreach(var w in x.Numbers)
{
values[y] = x.Numbers.Select(o => o.Order).Max();
y++;
break;
}
}
You can use IEnumerable.Max() :
foreach(var x in Category)
{
values[y] = x.Numbers.Select(o => o.Order).Max();
y++;
}
This can be accomplished relatively easily through LINQ as:
int[] values = new int[count];
foreach(var x in Category)
{
values.[y] = x.Numbers.OrderBy(w => w.Order).Reverse().First();
y++;
}
This orders the x.Numbers by their ascending order, reverses the order (to place the highest value first in the order), and then selects the first value.
Ensure with this method that you've actually got a value for x.Number, else you'll get an exception thrown by the .First() call.
If you're unable to use LINQ (e.g. if you're on .NET 2.0), then consider using a Dictionary with the Category as the key, and the highest Number as the value:
Dictionary<int, int> categoriesByHighestOrders = new Dictionary<int, int>();
foreach(var x in Category)
{
if (!categoriesByHighestOrders.Keys.Contains[x.SomeIndetifier])
categoriesByHighestOrders.Add(x.SomeIdentifier, 0);
foreach(var w in x.Numbers)
{
if (categoriesByHighestOrders[x.SomeIndetifier] < w.Order
categoriesByHighestOrders[x.SomeIndetifier] = w.Order;
}
}

Select all unique combinations of a single list, with no repeats, using LINQ

I have a list of numbers, and I need to create every possible unique combination of the numbers in the list, without repeats, using a LINQ query. So, for example, if I have { 1, 2, 3 }, the combinations would be 1-2, 1-3, and 2-3.
I currently use two for loops, like so:
for (int i = 0; i < slotIds.Count; i++)
{
for (int j = i + 1; j < slotIds.Count; j++)
{
ExpressionInfo info1 = _expressions[i];
ExpressionInfo info2 = _expressions[j];
// etc...
}
}
Is it possible to convert these two for loops to LINQ?
Thanks.
Sure - you can do it in a single call to SelectMany with an embedded call to Skip:
var query = slotIds.SelectMany((value, index) => slotIds.Skip(index + 1),
(first, second) => new { first, second });
Here's an alternative option, which doesn't use quite such an esoteric overload of SelectMany:
var query = from pair in slotIds.Select((value, index) => new { value, index })
from second in slotIds.Skip(pair.index + 1)
select new { first = pair.value, second };
These do basically the same thing, just in slightly different ways.
Here's another option which is much closer to your original:
var query = from index in Enumerable.Range(0, slotIds.Count)
let first = slotIds[index] // Or use ElementAt
from second in slotIds.Skip(index + 1)
select new { first, second };

Categories