Combine two List in C# using For Each - c#

I have two list objects in c# as mentioned below
List A
[0]
Count="0",
CountType="0",
InvTpeCode="DLX"
[1]
Count="0",
CountType="0"
InvTpeCode="STD"
List B
[0]
Count="2",
CountType="17"
[1]
Count="12",
CountType="14"
I have tried using foreach to update list a value with list b values but unfortunately i am not able to bring the desired output.
Note : Both the list are of same size only

Instead of for-loop you can also use Zip
var result = A.Zip(B, (a, b) => new Item {
InvTpeCode = a.InvTpeCode,
CountType = b.CountType,
Count = b.Count });

If the lists are the same size then a for loop will be enough:
for (int i=0; i< A.Count();i++)
{
A[i].Count = B[i].Count;
A[i].CountType = B.CountType;
}

a foreach-loop is unpractible here, i would do the following:
for(int i=0; i < A.Count(); i++)
{
A[i].Count = B[i].Count;
A[i].CountType = B[i].CountType;
}
But keep in mind this will die hard if List A is longer than B.

First assure that the lists are the same size.
var index = 0;
foreach ( ObjA itemA in listA) {
replaceValues(ObjA, listB[index]);
index++;
}
The method replaceValues should then replace the properties of ObjA with the properties of the item from listB (with the same position).
But I think it makes no sense to use an foreach here. A simple for-loop can be used - as you need the index of the current element anyway.

Related

Loop through list of strings to find different values

I have a list that is populated with different values:
e.g
{GBP, GBP, GBP, USD}
so far I have this:
List<string> currencyTypes = new List<string>();
for (int i = 0; i < currencyTypes.Count; i++)
{
if currencyTypes[i] != [i]
console.writeline("currencies are different");
}
So if the list has all the same entries, the if statement shouldnt fire
e,g {GBP, GBP, GBP, GBP}
however if any of the values are different from the rest then the if statement should notice the difference and fire.
this doesnt work however.
any ideas?
You could use LINQ to test whether all entries are the same
if (currencyTypes.Distinct().Count() > 1) {
Console.WriteLine("currencies are different");
}
Slightly more efficient for long lists:
if (currencyTypes.Count > 1 && currencyTypes.Distinct().Skip(1).Any()) {
Console.WriteLine("currencies are different");
}
This is more efficient because Any iterates at most one element unlike Count which iterates the whole list.
First of all, your list is empty. Maybe it's for the sake of the example. If not, initialize it with data. However, modify line 3 and 5 to this to fix the problem.
for (int i = 1; i < currencyTypes.Count; i++)
{
if (currencyTypes[i] != currencyTypes[i-1])
....
}
you should first group your data and find your result depending the group.
eg
List<string> currencyTypes = new List<string>() {"USD", "GBP", "GBP", "GBP" };
// group list items
var typeGroup = currencyTypes.GroupBy(t => t);
if (typeGroup.Count() > 1)
Console.WriteLine("currencies are different");
// .
// .
// also you can check what item is unique
foreach (var t in typeGroup.Where(g => g.Count() == 1 ))
{
Console.WriteLine($"{t.Single()} is different");
}

C# how can I loop through all Elements of a List <string>

I have the following problem. I have a list of strings and want to split these. After that, I want to give each Object Element a reference to an item of the List.
Example:
List<string> valueList = attr.Split(' ').ToList<string>();
This List has items like that:
name,string,age,int
For this example every Object needs to get 2 pieces of information, first the name (out of example: "name" or "age") and second the type (out of example: "string", "int").
Now I want to get an Object with this informations. So I created Objects and put these Objects into a List.
Example:
List<MyObject> listObjects = new List<MyObject>();
for (int i = 0; i < ValueList.Count; i++)
{
MyObject object = new MyObject();
if (ValueList.Any(s => s.StartsWith(modifier)) == true)
{
object.name = ValueList[i];
object.type = ValueList[i + 1];
}
listObjects.Add(object);
}
But with my solution, I'm getting a System.ArgumentOutOfRangeException. My explanation for this would be the foreach but I don't know a technique on how to get every item of the List of strings and add these to objects. Also what a problem is that 1 item of the List should have 2 elements (name, type) but with my method, I'm going through the foreach for every element. Is there any better way to do it in C# .Net Framework?
I suppose that you want something like this.
// Store your relevant keywords in a list of strings
List<string> datatypes = new List<string>{"string", "int"};
// Now loop over the ValueList using a normal for loop
// starting from the second elemend and skipping the next
for(int x = 1; x < ValueList.Count; x+=2)
{
// Get the current element in the ValueList
string current = ValueList[x];
// Verify if it is present in the identifiers list
if (datatypes.Contains(current)))
{
// Yes, then add the element before the current and the current to the MyObject list
MyObject obj = new MyObject;
obj.name = ValueList[x - 1];
obj.type = current;
listObjects.Add(obj);
}
}

Get the count of values from a dictionary C#

I have a Dictionary which has an ID as the key and a list of lists as the value. I would like to get the count of how many lists are inside the list. This appears to give the correct value when I query it whilst debugging but when I go to try and access that data it only gives a count of 1 rather than 2. I'm sure it's something I'm missing but I can't put my finger on it.
Here's the count when I check it through debugging:
And here's it when I try to access that count of 2:
The whole method is:
public static List<string> getStatisticsCSVHeaders(List<Items> itemList, Dictionary<int, List<List<Statistic>>> availableStats)
{
List<string> topRow = new List<string>();
for (int i = 0; i < availableStats.Values.Count; i++)
{
topRow.Add("Phase " + (i+1));
for (int k = 0; k < itemList.Count; k++)
topRow.Add(getMetricHeader(itemList[k], true));
}
return topRow;
}
I'd like to have the number of lists inside my list as the counter for the line i < availableStats.Values.Count.
EDIT:
I should mention I've tried availableStats.Values[0].Count but this won't compile.
Debugger shows that you have a single item in your dictionary, and that item is a list with 2 elements. Because your code is taking the count of item in the dictionary you're getting 1.
To get the number of all the items in all the lists in that dictionary, try LINQ and Sum:
availableStats.Values.Sum(x => x.Count)
In your question, because value contains a list, so it is possible that it may contain a null value, so it is necessary to do a null check for values otherwise you can get an error inside your LINQ query.
var totalCount = availableStats.Values.Sum(x => x==null? 0 : x.Count);
There is one more way to get same result as follows:
var totalCount = availableStats.Sum(x => x.Value==null? 0 : x.Value.Count);

How can I filter a list of strings, creating a list containing only those meeting my criteria?

In my application I want the program to search through a list, testing each list element. If the list element is the required length I then want this to be inserted into a new list. Below is the code I have already
List<string> foo = new List<string>();
List<string> newFoo = new List<string>();
for (int h = 0; h < l; h++);
{
// Here I want to search through every element of foo and if the element
// length is greater than say 5 i want to add it to the newFoo
}
I don't know how to search through each element and any examples I can find use LINQ which I don't want to do as I'm sure there is a simpler way. Any help much appreciated.
It sounds like you're looking for a foreach loop:
foreach (string element in foo)
{
if (element.Length > 5)
{
newFoo.Add(element);
}
}
However, assuming you start with an empty newFoo list, this is better done with LINQ:
List<string> newFoo = foo.Where(x => x.Length > 5).ToList();
Or if you already have an existing list, you can use:
newFoo.AddRange(foo.Where(x => x.Length > 5));
(In my experience it's more common to be creating a new list, mind you.)
If you're new to C#, you should probably make sure you understand the first form before you move on to use LINQ, lambda expressions etc.
Note that if you really, really want to use a straight for loop instead of a foreach loop, you can do so:
for (int i = 0; i < foo.Count; i++)
{
string element = foo[i];
if (element.Length > 5)
{
newFoo.Add(element);
}
}
... but I'd strongly recommend using foreach any time you want to iterate over a sequence and don't really care about the index of each entry.
You may use something like this (foreach loop):
foreach (String item in foo)
if (!Object.ReferenceEquals(null, item)) // <- be careful with nulls!
if (item.Length > 5)
newFoo.Add(item);
Or if you prefer index based access
for (int i = 0; i < foo.Count; ++i)
if (!Object.ReferenceEquals(null, foo[i])) // <- be careful with nulls!
if (foo[i].Length > 5)
newFoo.Add(foo[i]);
Yet another possibility is LINQ, e.g.
// Do not forget the nulls...
newFoo.AddRange(foo.Where(item => Object.ReferenceEquals(null, item) ? false : item.Length > 5));
Without Linq, you can do it with a simple loop
foreach(var f in foo)
{
if(f.Length > 5)
{
newFoo.Add(f);
}
}
But with Linq, it's even simpler
newFoo = foo.Where(f => f.Length > 5).ToList()
You can use LINQ to filter items with Length > 5 to your newFoo List
List<string> newFoo = foo.Where(r => r.Length > 5).ToList();
If you want to use simple for loop then:
for (int h = 0; h < foo.Count; h++)
{
if (foo[h] != null && foo[h].Length > 5)
newFoo.Add(foo[h]);
}
(Remember to remove the ; semicolon at the end of your for-loop, currently it will not do anything since it will consider ; as the only statement for the loop to work on)

Concurent foreach iteration of two list strings

Let's say I have two List<string>. These are populated from the results of reading a text file
List owner contains:
cross
jhill
bbroms
List assignee contains:
Chris Cross
Jack Hill
Bryan Broms
During the read from a SQL source (the SQL statement contains a join)... I would perform
if(sqlReader["projects.owner"] == "something in owner list" || sqlReader["assign.assignee"] == "something in assignee list")
{
// add this projects information to the primary results LIST
list_by_owner.Add(sqlReader["projects.owner"],sqlReader["projects.project_date_created"],sqlReader["projects.project_name"],sqlReader["projects.project_status"]);
// if the assignee is not null, add also to the secondary results LIST
// logic to determine if assign.assignee is null goes here
list_by_assignee.Add(sqlReader["assign.assignee"],sqlReader["projects.owner"],sqlReader["projects.project_date_created"],sqlReader["projects.project_name"],sqlReader["projects.project_status"]);
}
I do not want to end up using nested foreach.
The FOR loop would probably suffice. Someone had mentioned ZIP to me but wasn't sure if that would be a preferable route to go in my situation.
One loop to iterate through both lists (assuming both have same count):
for (int i = 0; i < alpha.Count; i++)
{
var itemAlpha = alpha[i] // <= your object of list alpha
var itemBeta = beta[i] // <= your object of list beta
//write your code here
}
From what you describe, you don't need to iterate at all.
This is what you need:
http://msdn.microsoft.com/en-us/library/bhkz42b3.aspx
Usage:
if ((listAlpga.contains(resultA) || (listBeta.contains(resultA)) {
// do your operation
}
List Iteration will happen implicitly inside the contains method. And thats 2n comparisions, vs n*n for nested iteration.
You would be better off with sequential iteration in each list one after the other, if at all you need to go that route.
This list is maybe better represented as a List<KeyValuePair<string, string>> which would pair the two list values together in a single list.
There are several options for this. The least "painful" would be plain old for loop:
for (var index = 0; index < alpha.Count; index++)
{
var alphaItem = alpha[index];
var betaItem = beta[index];
// Do something.
}
Another interesting approach is using the indexed LINQ methods (but you need to remember they get evaluated lazily, you have to consume the resulting enumerable), for example:
alpha.Select((alphaItem, index) =>
{
var betaItem = beta[index];
// Do something
})
Or you can enumerate both collection if you use the enumerator directly:
using (var alphaEnumerator = alpha.GetEnumerator())
using (var betaEnumerator = beta.GetEnumerator())
{
while (alphaEnumerator.MoveNext() && betaEnumerator.MoveNext())
{
var alphaItem = alphaEnumerator.Current;
var betaItem = betaEnumerator.Current;
// Do something
}
}
Zip (if you need pairs) or Concat (if you need combined list) are possible options to iterate 2 lists at the same time.
I like doing something like this to enumerate over parallel lists:
int alphaCount = alpha.Count ;
int betaCount = beta.Count ;
int i = 0 ;
while ( i < alphaCount && i < betaCount )
{
var a = alpha[i] ;
bar b = beta[i] ;
// handle matched alpha/beta pairs
++i ;
}
while ( i < alphaCount )
{
var a = alpha[i] ;
// handle unmatched alphas
++i ;
}
while ( i < betaCount )
{
var b = beta[i] ;
// handle unmatched betas
++i ;
}

Categories

Resources