For Each Element in Two Lists - c#

This is my code:
List<string> l1 = new List<string> { "a", "b", "c" };
List<string> l2 = new List<string> { "x", "y", "z" };
foreach (var item in l1)
{
item = MyFunction(item);
}
foreach (var item in l1)
{
item = MyFunction(item);
}
Is there a way to iterate both the Lists in a single foreach statement ?

Assuming the type of the List objects are the same you can use Concat.
foreach (var item in l1.Concat(l2))
{
item = MyFunction(item);
}

You could use the Concat() function:
foreach(var item in l1.Concat(l2))
item = MyFunction(item);
Be aware that reassigning the counter variable of an Enumerable-based loop can cause exceptions relating to changing the underlying IEnumerable.

Maybe something like this:
var mergedList = 11.Union(l2).ToList();
foreach (var item in mergedList)
{
item = MyFunction(item);
}
The Union removes any duplicates. The Concat() method does not. So Union might be preferrable. It depends on the composition of the lists.

Related

Iterate through IList<Hashtable> by index in ASP.NET MVC

I am having some trouble iterating through a IList<Hashtable>. I am trying to iterate it by index i.e.:
I have an IList<Hashtable> with 3 different Hashtables in it. I want to foreach each one by IList's index. In example:
I want first to foreach all KeyValuePairs in Hashtable in IList index=0. When finished do some stuff and then foreach all KeyValuePairs in Hashtable in IList index=1 and so on until all Hashtables are iterated through. Currently the code is as follows:
variable data is an IList<Hashtable> with 3 Hashtables in it.
foreach (Hashtable rowData in data[index])
{
some code here...
}
I get the following error:
Unable to cast object of type 'System.Collections.DictionaryEntry' to type 'System.Collections.Hashtable'.
If you want to iterate through an IList<HashTable> via the indexer operator:
IList<Hashtable> data = new List<Hashtable>
{
new Hashtable { { "a", "b"} },
new Hashtable { { "c", "d"}, {"e", "f"} },
new Hashtable { { "g", "h"} },
};
Then you can do the following:
//Iterate through the IList but interested only about the index
foreach (var index in data.Select((_, idx) => idx))
{
//Iterate through the Hashtable which contains DictionaryEntry elements
foreach (DictionaryEntry rowData in data[index])
{
Console.WriteLine($"{rowData.Key} = {rowData.Value}");
}
}
Reference for the Hashtable contains DictionaryEntry items.
The output will be either this:
a = b
c = d
e = f
g = h
or that:
a = b
e = f
c = d
g = h
Try this code
foreach(Hashtable rowData in data)
{
foreach(DictionaryEntry pair in rowData)
{
Console.WriteLine($"{pair.Key} {pair.Value}");
}
}

C# Iterate two list to no matchng / not containing with for loop only no linq

I would like to add "john" and "Bryan" only to the list of NonExistList.
I have to loop thru CollectionName and if names are not in ConfigName, I would like to add them to the new list.
List<string> CollectionNames = new List<string>() { "Thomas", "Bryan", "John", "Mike" };
List<string> ConfigNames = new List<string>() { "Thomas", "Mike" };
List<string> nonExist = new List<string>();
foreach (var nameC in CollectionNames)
{
foreach (var nameF in ConfigNames)
{
if(!nameC.Contains(nameF))
nonExist.Add(nameC);
}
}
So without using anything from System.Linq (I assume this is some kind of exercise) you can do something like this:
foreach (var nameC in CollectionNames)
{
bool isFound = false;
foreach (var nameF in ConfigNames)
{
if (nameC == nameF)
{
isFound = true;
break;
}
}
if (!isFound)
{
nonExist.Add(nameC);
}
}
So the idea is, you loop through CollectionNames, and for each value (nameC) you check it against all the values in ConfigNames. If you find a match, you break out of the loop (you don't need to check the rest of ConfigNames once you've found your match). If you reach the end of the loop through ConfigNames without finding your item, you add it to nonExist.

How to remove strings in list from another list?

I have 2 list which names are listA and listB.
I want to remove strings in listB which are in listA, but I want to do this in this way:
if listA contains: "bar", "bar", "bar", "foo"
and listB contains : "bar"
it removes only 1 bar and the result will be:
"bar", "bar", "foo"
the code I wrote removes all "bar":
List<string> result = listA.Except(listB).ToList();
You can try to remove it one by one:
foreach (var word in listB)
listA.Remove(word);
The Remove method will only remove one element at a time and is not throwing exception (but returning false) when the item is not found: https://msdn.microsoft.com/en-us/library/cd666k3e(v=vs.110).aspx
var listA = new List<string>() { "bar", "bar", "bar", "foo" };
var listB = new List<string>() { "bar" };
foreach (var word in listB){
listA.Remove(word);
}
Here is a more efficient way to do that:
var countB = new Dictionary<string, int>(listB.Count);
foreach (var x in listB)
{
int count;
countB.TryGetValue(x, out count);
countB[x] = count + 1;
}
listA.RemoveAll(x =>
{
int count;
if (!countB.TryGetValue(x, out count)) return false;
if (count == 1)
countB.Remove(x);
else
countB[x] = count - 1;
return true;
});
This is a faster method but it is likely to change the order of elements of first list. Steps:
Map the listA to a Dictionary<string, int> (let's call it listAMap), where key is the element of the list and value is the total number of times that value has occurred in listA;
Iterate through listB and for every element of listB, if that element is in the listAMap, reduce its count;
Get the keys of listMapA using Keys property of C# dictionaries, and iterate through all the keys. For every key which has positive value, add that key to another list a total of its count times. So if an entry is "bar" -> 2, then add "bar" twice in the new list.
Total run time of the algorithm is O(m + n), where m and n are number of elements in both the original lists. It is a better running time than other approaches mentioned here which have O(m * n) running time. Obviously this algorithm uses more space.
Supportive Code for the algorithm above:
//Step-1: Create the dictionary...
var listAMap = new Dictionary<string, int>();
foreach (var listAElement in listA)
{
listAMap.ContainsKey(listAElement) ? listAMap[listAElement]++ : listAMap.Add(listAElement, 1);
}
// Step-2: Remove the listB elements from dictionary...
foreach (var listBElement in listB)
{
if (listAMap.Contains(listBElement)) listAMap[listBElement]--;
}
//Step-3: Create the new list from pruned dictionary...
var prunedListA = new List<string>();
foreach (var key in listAMap.Keys)
{
if (listAMap[key] <= 0) continue;
for (var count = 0; count < listAMap[key]; count++)
{
prunedListA.Add(key);
}
}
//prunedListA contains the desired elements now.

Entity Framework: How to insert data while looping through multiple lists

I am attempting to insert data from two List.
I am able to successfully insert from one List but adding the second list using a foreach loop does not work as expected.
How do I loop through each of these list so that I can insert their values?
Code:
private void InsertList()
{
var listA = new List<string>();
var listB = new List<string>();
//Populate both list by splitting items in listbox
foreach (ListItem item in ListBox1.Items)
{
var components = item.Value.Split('/');
listA.Add(components.First());
listB.Add(components.Last());
}
using (DataContext dataContext = new DataContext())
{
foreach (var itemA in listA)
{
foreach (var itemB in listB)
{
LIST_OBJECTS listObject = new LIST_OBJECTS
{
LIST_ITEM_A = itemA,
LIST_ITEM_B = itemB
};
dataContext.LIST_OBJECTS.Add(listObject);
}
}
dataContext.SaveChanges();
}
}
What about a for loop?
for (var i = 0; i < listA.Count; i++)
{
LIST_OBJECTS listObject = new LIST_OBJECTS
{
LIST_ITEM_A = listA[i],
LIST_ITEM_B = listB[i]
};
dataContext.LIST_OBJECTS.Add(listObject);
}
Since you know from the creation of the Lists that they'll have the same number of elements, this is fine.
You can do it with LINQ
LIST_OBJECTS listObject = listA.Join(listB,
a=>listA.Indexof(a),
b=>listB.Indexof(b),
(a,b)=> new LIST_OBJECTS()
{
LIST_ITEM_A =a,
LIST_ITEM_B =b
}).ToList();

How to skip a specific position within a for each loop in c sharp?

List<string> liste = new List<String>
{
"A","B","C","D"
};
foreach (var item in liste)
{
System.Diagnostics.Debug.WriteLine(item.ToString());
}
for (int i = 0; i < liste.Count; i++)
{
if (i == 0)
continue;
System.Diagnostics.Debug.WriteLine(liste[i].ToString());
}
How do i skip a specific position in a foreach loop? I do not want to evaluate any values, but just skip the position x.
It has to be a specific position. One could choose position 0 or maybe position 7.
It is very easy to skip the first item in the list:
foreach(var item in list.Skip(1))
{
System.Diagnostics.Debug.WriteLine(item.ToString());
}
If you want to skip any other element at index n, you could write this:
foreach(var item in list.Where((a,b) => b != n))
{
System.Diagnostics.Debug.WriteLine(item.ToString());
}
In this example I use a lambda expression that takes two arguments: a and b. Argument a is the item itself, while argument b is the index of the item.
The relevant pages on MSDN that describe these extension methods are:
IEnumerable.Skip()
IEnumerable.Where()
You could even write your own extension method that allows you to skip an element in a list:
public static class MyEnumerableExtensions
{
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> list, int index)
{
var i = 0;
foreach(var item in list)
{
if(i != index)
yield return item;
i++;
}
}
}
This will allow you to write something like this to skip an item:
foreach(var item in list.SkipAt(2))
{
System.Diagnostics.Debug.WriteLine(item.ToString());
}
A foreach loop iterates over a collection that implements IEnumerable. The enumerator exposes the current item and a method to move onto the next item - it has no concept of an index.
You could always do:
var i = 0;
foreach (var item in liste) {
if (i++ == skip) continue;
Debug.WriteLine(item.ToString());
}
But this seems unnecessarily contrived. If you need an index, go with a for loop.
The other option is to remove the undesired item from the List before iterating:
foreach (var item in liste.Take(n-1).Union(liste.Skip(n))) {
Debug.WriteLine(item.ToString());
}
I love list's .ForEach, here's my take using #Elian's .SkipAt(n) and .ForEach:
var list = new List<String> { "A", "B", "C", "D" };
list = list.SkipAt(1).ToList();
list.ForEach(Debug.WriteLine);
You should try using the enhanced version of the Where extension method that allows you to filter on item and index.
Check the reference.
http://msdn.microsoft.com/en-us/library/bb549418.aspx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Verbatim list");
List<string> list = new List<String> { "A","B","C","D" };
foreach (var item in list)
{
Console.WriteLine(item.ToString());
}
Console.WriteLine("Filtered list");
int itemToSkip = 2;
foreach (var item in list.Where((item, index) => index != itemToSkip))
{
Console.WriteLine(item.ToString());
}
Console.ReadKey();
}
}
}
This will give you the following output.
Verbatim list
A
B
C
D
Filtered list
A
B
D
To skip a position inside the foreach loop, one option is that you can skip the action inside the foreach loop by using an if statement, like
foreach(var item in liste)
{
if (item != 'X')
{
//do something
}
}
But i am waiting for better solutions

Categories