How to change each element of a List<long>? - c#

I have a List of different DayTime (Ticks). I try to get a list of the time remaining from now to each time element.
List<long> diffliste = new List<long>(m_DummyAtTime);
// 864000000000 ≙ 24h
diffliste.ForEach(item => { item -= now; if (item < 0) item += 864000000000; });
// test, does also not work
// diffliste.ForEach(item => { item -= 500; });
However, the list is not changed. Do I miss something?
(now is DateTime.Now.TimeOfDay.Ticks)

var times = diffliste.Select(ticks => new DateTime(ticks) - DateTime.Now);
Will return a collection of TimeSpans between now and each time.
Without using Linq:
List<TimeSpan> spans = diffliste.ConvertAll(ticks => new DateTime(ticks) - DateTime.Now);
(modified as suggested by Marc)

You are changing a standalone copy in a local variable (well, parameter actually), not the actual value in the list. To do that, perhaps:
for(int i = 0 ; i < diffliste.Count ; i++) {
long val = diffliste[i]; // copy the value out from the list
... change it
diffliste[i] = val; // update the value in the list
}
Ultimately, your current code is semantically similar to:
long firstVal = diffliste[0];
firstVal = 42;
which also does not change the first value in the list to 42 (it only changes the local variable).

You cannot change the value of an item inside a foreach cycle.
You can do it using a classic for cycle or creating and assigning items to a new list.
for (int i = 0 ; i < diffliste.Count; i++)
{
long value = diffliste[i];
// Do here what you need
diffliste[i] = value;
}

The iteration var in a foreach cycle is immutable, so you cannot change it. You either have to create a new list or use a for cycle... see also here.

Related

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);
}
}

Modifying List and comparing with previous value

I have a list whose size is not fixed. In each iteration, the number of elements in the list may get decreased, increased or remain same but with different values.
In each iteration, I receive the newer list in a setter as following:
public List<int> IconsColor
{
get { return iconsColorList; }
set
{
newIconsColorList = new List<int>(value);
if (newIconsColorList.Count == iconsColorList.Count && newIconsColorList.All(iconsColorList.Contains))
return;
//Else
nIconsChanged = true;
//??????????????????????????
//?????????- How do I update Old list with New values
//Something like iconsColorList = newIconsColorList;
//but above line makes the If-condition true since both the lists are same now
}
}
How do I modify the elements of the previous list (iconsColorList) with new values (present in newIconsColorList)? And if the number of elements in the new list is greater than to that of the older list then, add the new element to the older list also.
So you want to merge both lists (update and add new):
public List<int> IconsColor
{
set
{
for (int i = 0; i < Math.Min(iconsColorList.Count, value.Count); i++)
{
if (value[i] != iconsColorList[i])
{
iconsColorList[i] = value[i];
nIconsChanged = true;
}
}
if (value.Count > iconsColorList.Count)
{
// append new items to the end of the list
iconsColorList.AddRange(value.Skip(iconsColorList.Count));
nIconsChanged = true;
}
}
}
Side-note: i hope the lack of a getter was just because it wasn't relevant. A property without a getter is not really useful and smells like fish. In this case it would just return iconsColorList;.

take one value from multiple loops

I have a list of arrays, of which i want to take one value from each array and build up a JSON structure. Currently for every managedstrategy the currency is always the last value in the loop. How can i take the 1st, then 2nd value etc while looping the names?
List<managedstrategy> Records = new List<managedstrategy>();
int idcnt = 0;
foreach (var name in results[0])
{
managedstrategy ms = new managedstrategy();
ms.Id = idcnt++;
ms.Name = name.ToString();
foreach (var currency in results[1]) {
ms.Currency = currency.ToString();
}
Records.Add(ms);
}
var Items = new
{
total = results.Count(),
Records
};
return Json(Items, JsonRequestBehavior.AllowGet);
JSON structure is {Records:[{name: blah, currency: gbp}]}
Assuming that I understand the problem correctly, you may want to look into the Zip method provided by Linq. It's used to "zip" together two different lists, similar to how a zipper works.
A related question can be found here.
Currently, you are nesting the second loop in the first, resulting in it always returning the last currency, you have to put it all in one big for-loop for it to do what you want:
for (int i = 0; i < someNumber; i++)
{
// some code
ms.Name = results[0][i].ToString();
ms.Currency = results[1][i].ToString();
}

Creating Collection dynamically in C#

I have an application that will continuously taking user's input and store the input in a List of class ItemsValue
How am I going to make it so that once the collection reaches 1000 counts, it will "stop" and a new collection will be created and so on.
For example:
List<ItemsValue> collection1 = new List<ItemsValue>();
//User input will be stored in `collection1`
if (collection1.count >= 1000)
//Create a new List<ItemsVales> collection2,
//and the user input will be stored in collection2 now.
//And then if collection2.count reaches 1000, it will create collection3.
//collection3.count reaches 1000, create collection4 and so on.
I don't know why, but you want a "list of lists": List<List<ItemsValue>>.
List<List<ItemsValue>> collections = new List<List<ItemsValue>>();
collections.Add(new List<ItemsValue>());
collections.Last().Add(/*user input*/);
if (collections.Last().Count >= 1000) collections.Add(new List<ItemsValue>());
I think you need List<List<ItemsValue>>
List<List<ItemsValue>> mainCollection = new List<List<ItemsValue>>();
int counter = 0;
if (counter == 0) mainCollection.Add(new List<ItemsValue>());
if(mainCollection[counter].Count < 1000) mainCollection[counter].Add(item);
else
{
mainCollection.Add(new List<ItemsValue>());
counter++;
mainCollection[counter].Add(item);
}
I don't know how is the rest of your code look like,but I would make that counter static.
Use a list of collections. If you have fixed size you can use a array instead of a list.
List<List<ItemsValue>> collections = new List<List<ItemsValue>>({new List<ItemsValue>()});
if(collections[collections.Count- 1].Count >= 1000)
{
var newCollection = new List<ItemsValue>();
// do what you want with newCollection
collections.Add(newCollection);
}
Try this:
List<List<ItemsValue>> collections = new List<List<ItemsValue>>({new List<ItemsValue>()});
if(collections[collections.Count-1].Count >= 1000)
{
collections.Add(new List<ItemsValue>());
}
Use the above if statement when you're adding an item to collections. To add an item to collections, use the following:
collections[collections.Count-1].Add(yourItem);

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