How to use linq instead of foreach loop in c# - c#

I'm trying to find solution for the next situation:
I have array with Item ids
var arrayIds = new long []{1076,2840,4839,3920,..., N};
I have method which returns one Item
public Item getItem(long id) {
return new Item{Id = id, Name = "name"};
}
Here trying to get all Items
var itemList = new List<Item>();
foreach(var id in arrayIds) {
itemList.Add(getItem(id));
}
Is it possible to use Linq here instead of foreach?
I've tried to write something like that
itemList = arrayIds.ForEach(x => getItem(x));
so I have the next error here:
There is no argument given that corresponds to the required formal parameter 'action' of 'Array.ForEach<T>(T[], Action<T>)'
So I don't know how to use Linq correctly.

I've tried to write something like that
itemList = arrayIds.ForEach(x => getItem(x));
ForEach() works on List<T>:
arrayIds.ToList().ForEach(x => getItem(x));
But what you want is:
var itemList = arrayIds.Select(getItem).ToList();
Or if you only want to enumerate the items:
var items = arrayIds.Select(getItem);

Use Select
var itemList = arrayIds.Select(x => getItem(x))

Related

Adding a List to SQL database (Entity Database)

I got a database with members, each member has a list of sports they do.
now I want to loop through a listbox and add every selected item to my database.
This is my database :
And this is my code :
foreach (var item in sportCheckedListBox.CheckedIndices)
{
int sportindex = Convert.ToInt32(item.ToString()) + 1;
var queryResult = from sp in context.Sports
where sp.sportnr == sportindex
select sp;
foreach (var sport in queryResult)
{
myMember.Sports.Add(sport);
}
}
This looks kinda 'shady', how could I do this better ?
One thing I'd do for sure is move the query out of the loop. Queries should never exist in loops for performance and maintainability reasons. LINQ knows how to translate a (new int[] { 0, 1, 2, ... }).Contains(column) construct into a WHERE column IN (0, 1, 2, ...) statement, so let's use that:
// Get all checked items together
var lookupIndices = sportCheckedListBox.CheckedIndices.Select(i => Convert.ToInt32(item.ToString()) + 1);
// Find all matching sport numbers
var queryResult = from sp in context.Sports
where lookupIndices.Contains(sp.sportnr)
select sp;
// Now loop over the results
foreach (var sport in queryResult)
{
myMember.Sports.Add(sport);
}
// save changes
I think you can just do AddRange:
myMember.Sports.AddRange(queryResult);
myMember.Sports.SaveChanges()
You may need to covert queryResult to an IEnumerable type if it's not already though.
There is nothing fundamentally wrong with your approach, but you can achieve it more concisely with Linq.
Instead of your foreach loop, if you always want to assign a new list you could use
myMember.Sports = queryResult.ToList();
If you want to instead concatenate results to an existing list, you could use
myMember.Sports = myMember.Sports.Concat(queryResult.ToList());
If you wanted to do the same as above, but not have any duplicates (as defined by the object you are adding), instead
myMember.Sports = myMember.Sports.Union(queryResult.ToList());

How to convert the following foreach loop to linq format?

Code:
foreach (var item in items)
testItems.Add(new TestItem { Header = item.TestItemTypeName, Content = item });
testItems is of type ObservableCollection<TabItem>
How to convert the above foreach loop to linq format? Thanks.
How about
items.ForEach(i => testItems.Add(
new TestItem
{
Header = i.TestItemTypeName,
Content = i
}));
Given that items is ObservableCollection<TabItem>
you could try
items.ToList().ForEach(i => testItems.Add(
new TestItem
{
Header = i.TestItemTypeName,
Content = i
}));
Providing that testItems has AddRange function, i.e. inherits from List:
testItems.AddRange(items.Select(item => new TestItem{ Header = item.TestItemTypeName, Content = item }));
As you have mentioned,this is an ObservableCollection, so the method is not available. In that case, the way you provided is the simplest possible. However, if you need to use this functionality more often, consider checking the following link:
ObservableCollection Doesn't support AddRange method, so I get notified for each item added, besides what about INotifyCollectionChanging?
Or perhaps:
var testItems = items
.Select(item =>
new TestItem {
Header = item.TestItemTypeName,
Content = item
})
.ToList();

Finding a specfic int in a List

I have a list which is created from a Class:
class Vara
{
public int streckKod { get; set; }
public string artNamn { get; set; }
}
And the list looks like this:
List<Vara> minaVaror = new List<Vara>();
And I add to the list with this line:
minaVaror.Add(new Vara() {streckKod = inputBox1, artNamn = textBox2.Text });
But what I'm stuck at is how I can find a specific int within the list. Let's say I'm searching for the item in my list holding the number 293 in the variable streckKod.
I've tried using .IndexOf function but I haven't gotten it to work properly.
Also would it be possible to get the item number that the specific number is located in?
If you want to find all items whose streckKod value is 293 use Where
var items = minaVaror.Where(i => i.streckKod == 293);
If interested in only first item use FirstOrDefault -
var item = minaVaror.FirstOrDefault(i => i.streckKod == 293);
FirstOrDefault will return null in case no item exist in collection with value 293.
Make sure you add namespace System.Linq in your class to use these LINQ extension methods.
Use Linq
minaVarror.Find(item=>item.strekKod == 293);
Adding to Rohit Vats answer...
When you have found your item, with either Where or FirstOrDefault you can get the index by doing:
var item = minaVaror.FirstOrDefault(i => i.streckKod == 293);
// Get index of Vara (item) with streckKod = 293
int index = minaVaror.IndexOf(item);
As IndexOf returns the position of an exact item (Vara) within the list minaVaror

Returning list of list values (consolidated)

I want to be able to return a list of all "list values" coming from the query.. 'query' below returns multiple rows of results back from db, each as an item in a list. A sample result back from db would look like...
sample query results when I put break point: (this is what first line of code below 'query' returns from db)
Name = John ; Address = 1230, Ewded ; listOfCities = "NY, CH, LA"
Name = Eric; Address = 12 , Ewded ; listOfCities = "BO, SE, OR"
Code:
List<Index.Result> query = getresultsbackfromdb();
// query content at this point looks like above 1,2
List<string> result = new List<string>();
foreach (var item in query)
{
results.Add(item.listCities);
//'results' list takes in string and not a list
//How do I return a consolidated list of items
}
return result; // this should have ""NY, CH, LA, BO, SE, OR"
//I am trying to get a list of all cities from 1,2 included in
//one single list.
There is method in a List that allows you to add multiple items
foreach (var item in query)
{
results.AddRange(item.listCities);
}
Docs for List.AddRange Method.
Also, just in case if you need to filter out some repeated items, you can use a Distinct LINQ method.
You can try this code based on Split Method
var result = yourString.Split(',');
var input = "NY, CH, LA";
var result = input.Split(',');
And you can save this value in List<object>
var list = new List<object>();
list.Add(result );
You want the AddRange and string.Split methods
results.AddRange(string.Split(',', item.ListCities));
string.Split will split the string into an array wherever it finds the given character, and add range will add all items in an array to the list.
Try this:
var result = query.SelectMany(x => x.listOfCities.Split(','));
Or use
var result = query.SelectMany(x => x.listOfCities.Split(',')).Distinct();
to get the list without duplicates.
If you like Linq then you could do this one line:
using System.Linq;
List<string> result = query.SelectMany(s => s.listCities).ToList();
(This does essentially the same thing as oleksii's AddRange.)

How do I get a usabled List object for this code in C# using LINQ to XML?

Newbie to C# here....
I have the following code:
var xdoc = XDocument.Parse(xml);
var result = xdoc.Root.Elements("item")
.Select(itemElem => itemElem.Elements().ToDictionary(e => e.Name.LocalName, e => e.Value))
.ToList();
but when I try to use result as I would any List object, such as result.Item, it doesn't work.
What am I doing wrong? Why is result not coming back as a normal List object that I can manipluate in my code? Do I need to make another List object from it?
I am just trying to get the first Dictionary item out of the List and use it.
It depends on what you expected. Your code currently produces a List<Dictionary<string,string>>. So each entry in the list would be a dictionary.
You can access each dictionary as you usually would access list elements, i.e.
string firstResult = result[0]["key"];
The first part [0] is the indexer of the list the second part ["key"] is the indexer of the dictionary - this would return the value for the key "key" of the first dictionary in your list.
This assumes the list has at least one entry though for which you would have to check.
This is a List<Dictionary<String, String>>. Each element in the list is a Dictionary.
It would help to know what you wanted to do with it.
But some examples are:
//Get the First Dictionary Item, then Iterate through all the items in the first dictionary.
var firstItem = results.First();
foreach(var kvPair in firstItem)
{
var key = kvPair.Key;
var val = kvPair.Value;
}
//Loop through each Dictionary getting values from each.
foreach (var result in results)
{
var wordValue = result["word"];
var defValue = result["def"];
}
//Create a list of all the values for the Elements with the key "word".
var valuesForAllWords =
results
.Select(r => r["word"])

Categories