I have a list of strings that I would like to iterate through and change the values if certain items in the list if they match up to a string value in a separate list of objects.
User inputs an email address into an Event object that contains a list of EventMembers:
List<string> EventMembers
I would then like to check through all users in the database to find the username(e-mail address) that matches with the inputted e-mail address
i understand I cannot change values in a list using a foreach loop, but i'm lost with what to do with linq. Basically i'm trying to do something like this:
var allUsers = _userManager.Users
foreach (var a in allUsers)
{
foreach (var e in #event.EventMembers)
{
if (e == a.UserName)
{
e = a.FirstName + a.LastName;
}
}
}
The best thing would be to define an initial collection of members so you don't keep modifying the list while the foreach is still running. You could then check if EventMembers contain the username and then replace it by accessing the value with the index.
var allUsers = _userManager.Users;
List<string> Members;
foreach (var a in allUsers)
{
if (#event.EventMembers.Contains(a.UserName))
{
var index = #event.Members.IndexOf(a.UserName);
Members[index] = a.FirstName + a.LastName;
}
}
EventMembers = Members;
I need to find a way to use a for-loop to find how many strings that are the same word in the same array-list. I need to use the for-loop because everytime it loops and finds another word that is the same I want to add it to an int variable :the following is the code that have tried to use but it didn;t work. variable bedrooms kept saying that it is 0 when it is not
foreach (string row in RoomType) // RoomType is the ArrayList
{
if (row.Equals("Bedroom"))
{
bedrooms++;
}
}
This code works, which is based on your code. I am assuming that you are probably doing something in your code where bedrooms is getting re-declared during the looping. This is a guess though.
var RoomType = new ArrayList();
var bedrooms = 0;
RoomType.Add("workflow");
RoomType.Add("Bedroom");
RoomType.Add("Bedroom");
foreach (string row in RoomType) // RoomType is the ArrayList
{
if (row.Equals("Bedroom"))
{
bedrooms++;
}
}
Console.WriteLine(bedrooms);
A different way:
var row = RoomType.Cast<string>().ToArray();
var count = row.Aggregate(0, (c, i) => (i.Equals("Bedroom")) ? ++c : c);
If you are not compelled to use a loop, you could try starting with this:
int bedrooms = RoomType.ToArray().Count(row => row.Equals("Bedroom"));
If you are compelled to use a loop, then please post a bit more of the code so that we can see where and how these objects are being set.
I have two string inputs with that have been split so each item is distinguishable from the other (these items are product properties such as length, weight, finish, stain color, etc.). One string has the original values for the product while the other has the new values (whatever they may be--users can edit whichever product values they want).
Right now, I have the split strings producing the info that I want but I am not sure how to compare the results to each other since the individual product values are inside foreach loops.
This is what I have:
//checks to see which attributes have been changed/edited for the product
protected bool ifAttrChanged(string oldItm, string newItm)
{
bool retVal = false;
//get the original attributes of the product
string[] oldItms = oldItm.Split(',');
foreach (string oItm in oldItms)
{
if (oItm != "")
{
string[] oldThings = oItm.Split(',');
string oldies = oldThings.GetValue(0).ToString();
}
}
//get whatever new values have been entered for the product
string[] newItms = newItm.Split(',');
foreach (string nItm in newItms)
{
if (nItm != "")
{
string[] newThings = nItm.Split(',');
string newbies = newThings.GetValue(0).ToString();
}
}
if (newItms.ToString().Equals(oldItms.ToString(), StringComparison.Ordinal))
{
retVal = false;
Label3.Text += retVal.ToString() + "<br />";
}
else
{
retVal = true;
Label3.Text += retVal.ToString() + "<br />";
}
return retVal;
}
I would really like to compare the oldies string variable with the newbies string variable (weird names but I am not concerned about that) but they are each in their own foreach statement and I cannot access them elsewhere. How can I compare the old and new values of the two split strings successfully so I can obtain which values were changed and which values remained the same?
With all the strings splittend and stored in arrays (oldItems and newItems), and using System.Linq.
Try this:
var changedResults = newItems.Where(x => !oldItems.Any(y => x == y));
With this you will get a IEnumerable with all the string in newItems which no appear in oldItems array.
If you want to convert this to a list or something, add this:
var changedResults = newItems.Where(x => !oldItems.Any(y => x == y)).ToList();
I hope this helps
What is a "change"? Addition? Deletion? Modification?
If only addition, Oscar's method works. This is the same thing (set difference) but a little more concise:
var changedResults = newItems.Except(oldItems)
However, if a deletion is a "change" as well, you would need to consider it from both sides.
var changedResults = newItems.Except(oldItems).Union(oldItems.Except(newItems));
Since the sets are of only strings, there is no notion of modification.
I have a data table and i'm trying to loop through the rows and create a zipCode array. This issue that i'm only getting one number 4 times. I know I'm doin something wrong but can somebody point this out to me and give and explanation.
Thanks
public string bindMap()
{
using (dal.Sys.RegionTableAdapters.region_countyListTa ta = new Cea.WebApp.JobsEq.Dal.Sys.RegionTableAdapters.region_countyListTa())
{
List<string> code = new List<string>();
dal.Sys.Region.region_countyListDataTable dt = ta.GetData(region.RegionType, region.RegionCode);
foreach (var row in dt)
{
code.Add(region.ZipCode);
}//end foreach loop
string codes = string.Join(",", code.ToArray());
return codes.ToString();
}//end for each loop
}//end bind map
You aren't using the variable that you are iterating with.
foreach (var row in dt)
{
//Not sure how you will get ZipCode from the ROW, but you get the idea.
code.Add(row["ZipCode"]);
}//end foreach loop
As a general desc of the row/cell value, I use this general (NOTE: GENERAL) block:
foreach(var item : items) {
//before adding there is maybe some casting or other work...
listName.add(item["FieldName"]);
}
Understandable is that the listName is of type fieldNameType
Let's say I have a file that looks like this:
R34 128590 -74.498 109.728 0 0805_7
R33 128590 -74.498 112.014 0 0805_7
R15 128588 -68.910 127.254 0 0805_7
R32 128587 -65.354 115.189 0 0805_7
R35 128587 -65.354 117.348 0 0805_7
R38 128590 -65.354 119.507 0 0805_7
What I want to do is add the 2nd column to a list and have a counter count how many times that item occurs and outputs it with the number and then the counted amount of that number.
Is there a way to do this using a List? If so, how could I go about doing that?
I have tried messing around with things and this is where I was heading.. but it does not work properly
int lineCount = 1;
int itemCounter = 0;
foreach (var item in aListBox.Items)
{
// Creates a string of the items in the ListBox.
var newItems = item.ToString();
// Replaces any multiple spaces (tabs) with a single space.
newItems = Regex.Replace(newItems, #"\s+", " ");
// Splits each line by spaces.
var eachItem = newItems.Split(' ');
###
### HERE is where I need help ###
###
List<string> partList = new List<string>();
partList.Add(eachItem[1]);
if (partList.Contains(eachItem[1]))
itemCounter++;
else
partList.Add(eachItem[1]);
sw.WriteLine(lineCount + ": "+ partList + ": " + itemCounter);
lineCount++;
}
SO for the example above, it would output this:
1: 128590: 3 #lineCount, partList, itemCounter
2: 128588: 1
3: 128587: 2
Can someone help me figuring out how to properly do this?
use linq with count and group by (see Count- Grouped section).
create your partList outside the foreach loop and add each item to it inside the loop , so that it would contain all of the elements:
List<string> partList = new List<string>();
foreach (var item in aListBox.Items)
{
//regex stuff here...
partList.Add(eachItem[1]);
}
(in your example- {128590, 128590, 128588, 128587, 128587, 128590})
and then use LINQ to output the result-
var elementsWithCounts = from p in partList
group p by p into g
select new { Item = g.Key, Count = g.Count()};
I would either use a Linq query or a Dictionary
something like
List<string> items = new List<string>{"128590", "128590", "128588", "128587", "128587", "128590"};
Dictionary<string,int> result = new Dictionary<string,int>();
foreach( int item in items )
{
if(result.ContainsKey(item) )
result[item]++;
else
result.Add(item,1);
}
foreach( var item in result )
Console.Out.WriteLine( item.Key + ":" + item.Value );
Once you have the items split by space, I'm assuming you have a string array looking like so:
[0] = "R34"
[1] = "128590"
[2] = "-74.498"
[3] = "109.728"
[4] = "0"
[5] = "0805_7"
You can simply perform this operation with a Group By operation.
var items = aListBox.Items.Select(x => /* Split Code Here and Take Element 1 */).GroupBy(x => x);
foreach(var set in items)
{
Console.WriteLine(set.Key + " appeared " + set.Count() + " times.");
}
Basically, you are trying to do this by iterating once, and that is not really going to work, you are going to have to iterate twice, otherwise you will wind up doing an output every time you loop in the foreach, and even if your accurate you are going to be outputting a new line each time. If you need to really use a List instead of a keyed dictionary or hashtable which would be idea for this (key = number, value = count), then you need to build the list first, then summarize the list. You can either use LINQ Group By (which is a bit terse), or create a function that does something similar to what you already have. If you are trying to learn concepts, look at the code below, it could be more condensed but this should be fairly easy to read.
List<string> partList = new List<string>();
List<string> displayedNumbers = new List<int>();
// Build the original list first.
foreach (var item in aListBox.Items)
{
// Creates a string of the items in the ListBox.
var newItems = item.ToString();
// Replaces any multiple spaces (tabs) with a single space.
newItems = Regex.Replace(newItems, #"\s+", " ");
// Splits each line by spaces.
var eachItem = newItems.Split(' ');
partList.Add(eachItem[1]);
}
// Now run through that list and count how many times the same number occurs.
// You will need two loops for this since your list is a single dimension collection.
foreach(var number in partList)
{
var innerList = partList;
// set this to zero because we are going to find at least 1 duplicate.
var count = 0;
foreach(var additionalNumber in innerList)
{
if(additionalNumber == number)
{
// If we find anymore increase the count each time.
count += 1;
}
}
// Now we have the full count of duplicates of the outer number in the list.
// If it has NOT been displayed, display it.
if(!displayedNumbers.Contains(number))
{
sw.WriteLine(partList + ": " + count);
displayedNumbers.Add(number);
}
}
Use a hash table instead ofa list. You can save the key as 128590,... and the value the number of times it has occurred.
Before you insert the new value check if it is already present in the hashtable by using the Contains operation and if it is increment the value.
I think the biggest problem is getting from raw lines of your text field to individual values. My guess is this is a tab-delimited file with a known constant number of columns, in which case you could use String.Split() to separate the sub-strings. Once you have the strings separated, you can count the instances of the proper column pretty easily with a little LINQ. Given a list or collection of your file's lines:
var histogram = myListOfLines
//Split each string along spaces or tabs, and discard any zero-length strings
//caused by multiple adjacent delimiters.
.Select(s=>s.Split(new[]{'\t',' '}, StringSplitOptions.RemoveEmptyEntries))
//Optional; turn the array of strings produced by Split() into an anonymous type
.Select(a=>new{Col1=a[0], Col2=a[1], Col3=a[2], Col4=a[3], Col5=a[4]})
//Group based on the values of the second column.
.GroupBy(x=>x.Col2)
//Then, out of the grouped collection, get the count for each unique value of Col2.
.Select(gx=>new{gx.Key, gx.Count()});