Foreach and modification to iteration variable - c#

What's the proper way to do this?
foreach(Object obj in ObjectList<Object>)
{
Object changedObject= GetInfo(obj);
obj=changedObject; //no good
obj.prop1 = changedObject.prop1; //ok?
obj.prop2 = changedObject.prop2; //ok?
better way?
}

Use a for loop instead:
for (int i = 0; i < list.Count; i++)
{
Object changedObject = GetInfo(list[i]);
list[i] = changedObject;
}
You could also use LINQ, and append .ToList() if you need a list instead of an IEnumerable<T>:
var query = result.Select(o => GetInfo(o));

I think you're better off creating a new list of objects, ie:
var newList = new List<Object>();
foreach(Object obj in ObjectList<Object>)
{
newList.Add(GetInfo(obj));
}
Then either replace ObjectList with newList or just return it from whatever you're doing

Related

Get listitems according to the index of another list

I have a List<List<string>> with three nested lists. Now I need to check if List[1] equals a certain string and if so, check if the value at this index in List[2] has another certain string. If both conditions return true, then I need to get that certain index and get the item of List[0].
For example:
var list = Titles[0];
var list2 = Titles[1];
var list3 = Titles[2];
foreach (var item in list2)
{
if (item.Contains("Dt."))
{
int idx = list2.IndexOf(item);
var value = list3.ElementAt(idx);
if (value.Contains("25.04.2017"))
{
var newList = list.ElementAt(idx);
}
}
}
This approach doesn't seem very efficient in regards to performance, especially if the nested list contains ~9000 items.
I tried to get the result via lambda expressions first, but I'm not sure if this is the right approach either.
What would be the best or most efficient solution?
Eliminate ElementAt with direct access to index. I believe ElementAt iterates over List in order to get i'th element
Eliminate usage of IndexOf with index provided by for loop I believe IndexOf iterates over List in order to find matching element.
var list = Titles[0];
var list2 = Titles[1];
var list3 = Titles[2];
for (int i = 0 ; i < list2.Count; ++ i)
{
var item = list2[i];
if (item.Contains("Dt."))
{
var value = list3[i];
if (value.Contains("25.04.2017"))
{
var newList = list[i];
}
}
}
Note if size of list2 is greater than size of list or list3 then you potentially get IndexOutOfRangeException
Lambda equivalent for your code:
if(list2.Any(item => item.Contains("Dt.")))
{
int idx = list2.IndexOf("Dt.");
if(list3.ElementAt(idx).Contains("25.04.2017"))
{
var newList = list.ElementAt(idx);
}
}
for (int i = 0; i < list2.Count; ++i)
{
var item = list2[i];
if (item.Contains("Dt."))
{
var value = list3[i];
if (value.Contains("25.04.2017"))
{
var newList = list[i];
break; // Break the loop :-)
}
}
}

How update a list in a foreach

I have a foreach of a List and i want to Update the list or (i donĀ“t know wich is better) create a new one with the new values. How to do this ?
My code is bigger than this because i am decrypting, but if help me with this simple, will fix the other.
foreach (Envolvido envolvido in ListaDados.ItemsSource)
{
for (int i = 0; i < ListaDados.ItemsSource.OfType<object>().Count(); i++)
{
var suspid = Convert.FromBase64String(envolvido.SUSPID);
var ivnome = Convert.FromBase64String(envolvido.IVNOME);
}
}
So, with the help of all, i got the correct answer !
List<Envolvido> mylist = t.Result;
for (int index = 0; index < mylist.Count(); index++)
{
var items = mylist.ToList();
Envolvido envolvido = items[index];
envolvido.SUSPID= Convert.FromBase64String(envolvido.SUSPID);
envolvido.IVNOME = Convert.FromBase64String(envolvido.IVNOME);
}
THANKS!
Use for for modifing lists. NOT foreach.
As it says on MSDN:
The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop.
List<Envolvido> mylist = t.Result;
for (int index = 0; index < mylist.Count(); index++)
{
var items = mylist.ToList();
Envolvido envolvido = items[index];
envolvido.SUSPID= Convert.FromBase64String(envolvido.SUSPID);
envolvido.IVNOME = Convert.FromBase64String(envolvido.IVNOME);
}

How to iterate through IEnumerable collection using for each or foreach?

I want to add one by one values but in for loop how can I iterate
through one by one values and add it inside dictionary.
IEnumerable<Customer> items = new Customer[]
{
new Customer { Name = "test1", Id = 111},
new Customer { Name = "test2", Id = 222}
};
I want to add { Name = "test1", Id = 111} when i=0
and want to add { Name = "test2", Id = 222} when i=1 n so on..
Right now i'm adding full collection in every key.(want to achieve this using foreach or forloop)
public async void Set(IEnumerable collection)
{
RedisDictionary<object,IEnumerable <T>> dictionary = new RedisDictionary>(Settings, typeof(T).Name);
// Add collection to dictionary;
for (int i = 0; i < collection.Count(); i++)
{
await dictionary.Set(new[] { new KeyValuePair<object,IEnumerable <T> ( i ,collection) });
}
}
If the count is need and the IEnumerable is to be maintained, then you can try this:
int count = 0;
var enumeratedCollection = collection.GetEnumerator();
while(enumeratedCollection.MoveNext())
{
count++;
await dictionary.Set(new[] { new KeyValuePair<object,T>( count,enumeratedCollection.Current) });
}
New version
var dictionary = items.Zip(Enumerable.Range(1, int.MaxValue - 1), (o, i) => new { Index = i, Customer = (object)o });
By the way, dictionary is a bad name for some variable.
I'm done using
string propertyName = "Id";
Type type = typeof(T);
var prop = type.GetProperty(propertyName);
foreach (var item in collection)
{
await dictionary.Set(new[] { new KeyValuePair<object, T>(prop.GetValue(item, null),item) });
}
So you want to a an item from the collection to the dictionary in the for loop?
If you cast your IEnumerable to a list or an array, you can easily access it via the index. For example like this:
Edit: Code at first created a list every time it looped, which should of course be avoided.
var list = collection.ToList(); //ToArray() also possible
for (int i = 0; i < list.Count(); i++)
{
dictionary.Add(i, list[i]);
}
I'm not 100% if that is what you need, though. More details to your question would be great.

Use LINQ to populate controls from object array

I am just trying to find a better way to populate some RadioButtonList controls. There are a set number of these on the usercontrol.ascx. The code is what I am currently using but I am still not very good with Linq and was wondering if there's a better way to do this.
quizId1 = quiz.Items[0].questionId;
pTag1.InnerText = quiz.Items[0].QuestionText;
foreach (Question q in quiz.Items[0].AnswerChoice)
{
radiobuttonlist1.Items.Add(new ListItem(q.Value, q.answerId));
}
same for radiobuttonlist2 but using Items[1] etc.
quizId2 = quiz.Items[1].questionId;
pTag2.InnerText = quiz.Items[1].QuestionText;
foreach (Question q in quiz.Items[1].AnswerChoice)
{
radiobuttonlist2.Items.Add(new ListItem(q.Value, q.answerId));
}
Sorry, the InnerText is a server side 'P' tag, pTag1, pTag2 etc.
Try this
var listItems = (from x in quiz.Items[0].AnswerChoice
select new ListItem { Text = q.Value, Value = q.answerId }
).ToList<ListItem>();
radiobuttonlist1.DataSource = listItems;
radiobuttonlist1.DataBind();
I suppose you could do something like this:
var listItems = from q in quiz.Items[0].AnswerChoice
select new ListItem(q.Value, q.answerId);
radioButtonlist1.Items.AddRange(listItems.ToArray());
though I'm not really sure if that buys you anything other than experience with LINQ...
I assume you want to use ling to popiulate several controls, not an individual control.
Linq is for querying, not updating. To update you still need either for or foreach loops.
If your RadioButtonList objects are in a collection, you could just loop over them:
var radioList = new [] {radiobuttonlist1, radiobuttonlist2, ...};
for(int i = 0; i < quiz.Items.Length; i++)
{
var quizId = quiz.Items[i].questionId;
radioList[i].InnerText = quiz.Items[i].QuestionText;
radioList[i].Items.AddRange(quiz.Items[i]
.AnswerChoice
.Select(q => => new ListItem(q.Value, q.answerId))
.ToArray()
);
}
or use DataSource as others have suggested:
var radioList = new [] {radiobuttonlist1, radiobuttonlist2, ...};
for(int i = 0; i < quiz.Items.Length; i++)
{
var quizId = quiz.Items[i].questionId;
radioList[i].InnerText = quiz.Items[i].QuestionText;
radioList[i].DataSource = quiz.Items[i].AnswerChoice;
radioList[i].DataTextField = "Value";
radioList[i].DataValueField = "answerId";
}
but there's no Linq way to populate several controls.

How I get a Arraylist with not double values?

I want do get a Departmentlist from the Active Directory for this I use the Directoryentry and the DirectorySearcher class. I get the list of departments but how I can delete the double values in this list.
for example my list now:
it
it
it
vg
per
vg
...
And I want only one of this values in the list how this:
it
vg
per
...(other departments)
I want to use this list for a dropDownlist list.
my Code:
public static void GetAllDepartments(string domaincontroller)
{
ArrayList list = new ArrayList();
int Counter = 0;
string filter = "(&(objectClass=user)(objectCategory=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(sn=*)(|(telephoneNumber=*)(mail=*))(cn=*)(l=*))";
List<User> result = new List<User>();
DirectoryEntry Entry = new DirectoryEntry(domaincontroller);
DirectorySearcher Searcher = new DirectorySearcher(Entry, filter);
foreach (SearchResult usr in Searcher.FindAll())
{
result.Add(new User()
{
department = GetLdapProperty(usr, "Department")
});
Counter++;
}
for (int i = 0; i < Counter; i++)
{
list.Add(result[i].department);
}
}
How I can show only one value in the Arraylist?
First of all, I recommend that instead of using an ArrayList, use a Strongly-Typed list.
Then, use the Distinct() method to only get a list of unique values (no duplicates).
For instance:
List<String> list = new List();
....
for (int i = 0; i < Counter; i++)
{
list.Add(result[i].department.ToString());
}
var noDuplicates = list.Distinct();
Try Distinct() in System.Linq extensions :
list = list.Distinct();
You can also use the Exists clause to see if the element already exists in the list.
using System.Linq;
for (int i = 0; i < Counter; i++)
{
bool deptExists = list.Exists(ele => ele == result[i].department);
if(!deptExists){
list.Add(result[i].department);
}
}
Use the Enumerable.Distinct Method method.
Use a HashSet and only insert the non-duplicate values.
HashSet<string> list = new HashSet<string>();
...
for (int i = 0; i < Counter; i++)
{
string dep = result[i].department.ToString();
// true if dep was added, false if not. No exception at this point.
list.Add(dep);
}

Categories