Can I access the index from within a foreach? - c#

In PHP I can do this:
$list = array("element1", "element2");
foreach ($list as $index => $value) {
// do stuff
}
In C# i can write:
var list = new List<string>(){ "element1", "element2" };
foreach (var value in list)
{
// do stuff ()
}
But how can I access the index-value in the C# version?

Found multiple solutions on: foreach with index
I liked both JarredPar's solution:
foreach ( var it in list.Select((x,i) => new { Value = x, Index=i }) )
{
// do stuff (with it.Index)
}
and Dan Finch's solution:
list.Each( ( str, index ) =>
{
// do stuff
} );
public static void Each<T>( this IEnumerable<T> ie, Action<T, int> action )
{
var i = 0;
foreach ( var e in ie ) action( e, i++ );
}
I chose Dan Finch's method for better code readability.
(And I didn't need to use continue or break)

I'm not sure it's possible to get the index in a foreach. Just add a new variable, i, and increment it; this would probably be the easiest way of doing it...
int i = 0;
var list = new List<string>(){ "element1", "element2" };
foreach (var value in list)
{
i++;
// do stuff ()
}

If you have a List, then you can use an indexer + for loop:
var list = new List<string>(){ "element1", "element2" };
for (int idx=0; idx<list.Length; idx++)
{
var value = list[idx];
// do stuff ()
}

If you want to access index you should use for loop
for(int i=0; i<list.Count; i++)
{
//do staff()
}
i is the index

Related

How to name an array based on a variable name

Working is:
foreach (string feature in alpha)
{
for (int i=0; i < l.Count; i++)
{
if (l[i] == feature)
{
string[] ("{0}",feature) = new string[];
}
}
}
string[] ("{0}",feature) = new string[]; is incorrect. What needs to be done is, whenever there is a match for the condition (l[i] == feature) , create a new string array as: string[] (whatever string there is in feature) = new string[].
Possible?
I think a dictionary is what you want.
var arrays = alpha
.Where(a => l.Contains(a))
.ToDictionary(a => a, a => new List<string>());
Then to access one:
List<string> array = arrays["somefeature"];
Also stop using arrays, there's almost no good reason to choose them over the other collection types. I have used List because you said you want to append to it.
You could use a sorted list where the key value would be your feature;
var featureList = new SortedList<string, string[]>();
foreach (string feature in alpha)
{
var matchingFeatures = new List<string>();
for (int i = 0; i < l.Length; i++)
{
if (l[i] == feature)
{
matchingFeatures.Add(l[i]);
}
}
featureList.Add(feature, matchingFeatures.ToArray());
}

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.

Counting words using LinkedList

I have a class WordCount which has string wordDic and int count. Next, I have a List.
I have ANOTHER List which has lots of words inside it. I am trying to use List to count the occurrences of each word inside List.
Below is where I am stuck.
class WordCount
{
string wordDic;
int count;
}
List<WordCount> usd = new List<WordCount>();
foreach (string word in wordsList)
{
if (usd.wordDic.Contains(new WordCount {wordDic=word, count=0 }))
usd.count[value] = usd.counts[value] + 1;
else
usd.Add(new WordCount() {wordDic=word, count=1});
}
I don't know how to properly implement this in code but I am trying to search my List to see if the word in wordsList already exists and if it does, add 1 to count but if it doesn't then insert it inside usd with count of 1.
Note: *I have to use Lists to do this. I am not allowed to use anything else like hash tables...*
This is the answer before you edited to only use lists...btw, what is driving that requirement?
List<string> words = new List<string> {...};
// For case-insensitive you can instantiate with
// new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
Dictionary<string, int> counts = new Dictionary<string, int>();
foreach (string word in words)
{
if (counts.ContainsKey(word))
{
counts[word] += 1;
}
else
{
counts[word] = 1;
}
}
If you can only use lists, Can you use List<KeyValuePair<string,int>> counts which is the same thing as a dictionary (although I'm not sure it would guarantee uniqueness). The solution would be very similar. If you can only use lists the following will work.
List<string> words = new List<string>{...};
List<string> foundWord = new List<string>();
List<int> countWord = new List<int>();
foreach (string word in words)
{
if (foundWord.Contains(word))
{
countWord[foundWord.IndexOf(word)] += 1;
}
else
{
foundWord.Add(word);
countWord.Add(1);
}
}
Using your WordCount class
List<string> words = new List<string>{...};
List<WordCount> foundWord = new List<WordCount>();
foreach (string word in words)
{
WordCount match = foundWord.SingleOrDefault(w => w.wordDic == word);
if (match!= null)
{
match.count += 1;
}
else
{
foundWord.Add(new WordCount { wordDic = word, count = 1 });
}
}
You can use Linq to do this.
static void Main(string[] args)
{
List<string> wordsList = new List<string>()
{
"Cat",
"Dog",
"Cat",
"Hat"
};
List<WordCount> usd = wordsList.GroupBy(x => x)
.Select(x => new WordCount() { wordDic = x.Key, count = x.Count() })
.ToList();
}
Use linq: Assuming your list of words :
string[] words = { "blueberry", "chimpanzee", "abacus", "banana", "abacus","apple", "cheese" };
You can do:
var count =
from word in words
group word.ToUpper() by word.ToUpper() into g
where g.Count() > 0
select new { g.Key, Count = g.Count() };
(or in your case, select new WordCount()... it'll depend on how you have your constructor set up)...
the result will look like:
First, all of your class member is private, thus, they could not be accessed somewhere out of your class. Let's assume you're using them in WordCount class too.
Second, your count member is an int. Therefore, follow statement will not work:
usd.count[value] = usd.counts[value] + 1;
And I think you've made a mistype between counts and count.
To solve your problem, find the counter responding your word. If it exists, increase count value, otherwise, create the new one.
foreach (string word in wordsList) {
WordCount counter = usd.Find(c => c.wordDic == word);
if (counter != null) // Counter exists
counter.count++;
else
usd.Add(new WordCount() { wordDic=word, count = 1 }); // Create new one
}
You should use a Dictionary as its faster when using the "Contains" method.
Just replace your list with this
Dictionary usd = new Dictionary();
foreach (string word in wordsList)
{
if (usd.ContainsKey(word.ToLower()))
usd.count[word.ToLower()].count++;
else
usd.Add(word.ToLower(), new WordCount() {wordDic=word, count=1});
}

How to loop all functions?

I am working on a project and I've got stuck :(.... I have 9 (nine) functions with the name:
getM1(), getM2(), getM3(), getM4()....getM5(). And all of these functions return a value.
Now I need to make a loop which checks the value of these functions. Something like this:
public void show()
{
for (int i = 1; i <= 9; i++)
{
if (obj.getM[i]() == 1)
{
.......;
}
}
}
Of course it shows me an error because the getM doesn't contain any index..
And I wanted to ask you, can you help me with this? Or does anybody have another idea how could I check all getM() functions?
Create an array of Func<int> delegates and use it to access your methods:
var functions = new Func<int>[9];
functions[0] = getM1;
functions[1] = getM2;
functions[2] = getM3;
// (...)
for (int i = 0; i <= 9; i++)
{
if (functions[i]() == 1)
{
;
}
}
What about putting the functions into an Array:
var functionList = new [] { obj.getM1, obj.getM2, ... };
And then loop at it
foreach (var f in functionList)
{
if (f() == 1)
...
}
Replace the methods with this:
int getM(int index)
If this and the other solutions suggested really don't make any sense, you can do what you want using reflection:
var t = obj.GetType();
for (int i = 1; i <= 9; i++)
{
var m = t.GetMethod("getM" + i);
int result = (int)m.Invoke(obj, null);
}
Make an array of Func<T>, where T is the return type of your functions. Then you would be able to call your functions more or less the way you described in your code.
For example, if your functions return int, you can do this:
Func<int>[] ems = new Func<int>[] {
() => obj.getM1(), () => obj.getM2(), () => obj.getM3()
, () => obj.getM4(), () => obj.getM5(), () => obj.getM6()
, () => obj.getM7(), () => obj.getM8(), () => obj.getM9()
};
foreach (Func<int> em in ems)
{
if (em() == 1)
{
.......;
}
}
public void Show()
{
Func<int>[] arr = new[]
{
obj.GetM1,
obj.GetM2,
...
};
foreach(Func<int> func in arr)
{
if (func() == 1)
{
//
}
}
}
You could store all of these methods in a list, loop over the list an execute them.
var funcList = new List<Func<int>>{ getM1, getM2, ... };
Then you can loop over the list and execute each method.
foreach(var func in funList)
{
if(func() == 1)
...
}

How to compute rank of IEnumerable<T> and store it in type T

I want to compute rank of element in an IEnumerable list and assign it to the member. But below code works only when called 1st time. 2nd time call starts from last rank value. So instead of output 012 and 012, I'm getting 012 and 345
class MyClass
{
public string Name { get; set; }
public int Rank { get; set; }
}
public void SecondTimeRankEvaluvate()
{
MyClass[] myArray = new MyClass[]
{
new MyClass() { Name = "Foo" },
new MyClass() { Name = "Bar" },
new MyClass() { Name = "Baz" }
};
int r = 0;
var first = myArray.Select(s => { s.Rank = r++; return s; });
foreach (var item in first)
{
Console.Write(item.Rank);
}
// Prints 012
Console.WriteLine("");
foreach (var item in first)
{
Console.Write(item.Rank);
}
// Prints 345
}
I understand that the variable r is being captured (closure) and reused when called 2nd time. I don't want that behavior. Is there any clean way to compute rank and assign it?
Also r variable (in actual code) isn't in the same scope where foreach loop is present. It is in a function which returns var first
var first = myArray.Select((s, i) => { s.Rank = i; return s; });
LINQ uses lazy evaluation and runs the Select part every time you use myArray.
You can force evaluation to happen only once by storing the result in a List.
Change
var first = myArray.Select(s => { s.Rank = r++; return s; });
to
var first = myArray.Select(s => { s.Rank = r++; return s; }).ToList();
Another way would be to join myArray with a new sequence using Zip every time, like this
var first = myArray.Zip(Enumerable.Range(0, int.MaxValue), (s, r) =>
{
s.Rank = r;
return s;
});
You shouldn't use LINQ if you're not querying the collection.
To update each item in an array, use a for loop:
for (int i = 0; i < myArray.Length; i++)
{
myArray[i].Rank = i;
}
To update each item in an enumerable, use a foreach loop:
int r = 0;
foreach (var item in myArray)
{
item.Rank = r++;
}

Categories