Looping array inside list in C# - c#

I have a list of arrays that contains multiple arrays.
Each array has 2 indexes.
First, I want to loop the list. Then I want to loop the array inside the list.
How can I do that ?
I tried to use this way, but it doesn't work:
1. foreach (string[] s in ArrangList1)
2. {
3. int freq1 = int.Parse(s[1]);
4. foreach (string[] s1 in ArrangList)
5. {
6. int freq2 = int.Parse(s1[1]);
7. if (freq1 < freq2)
8. {
9. backup = s;
10. index1 = ArrangList1.IndexOf(s);
11. index2 = ArrangList.IndexOf(s1);
12. ArrangList[index1] = s1;
13. ArrangList[index2] = s;
14. }
15. backup = null;
16. }
17. }
It give me error in line 4.
I try to do the loop using other way, but I don't know how to continue.
for (int i = 0; i < ArrangList1.Count; i++)
{
for (int j = 0; j < ArrangList1[i].Length; j++)
{
ArrangList1[i][1];
}
}
I use C#.
How can I fix this problem?

The error in line4 might be due to a typo using ArrangList. I think you only have ArrangList1 defined. Regardless, the logic is wrong. If you have a list containing arrays, you want to do a foreach on the list, then a foreach on each list item (which is an array).
It's not clear what your types are, so I'm assuming that ArrangList is a list of string arrays.
foreach(string[] s in ArrangList1)
{
foreach(string innerS in s)
{
//now you have your innerString
Console.WriteLine(innerS);
}
}
In your second example,
You have a typo as well...
for (int i = 0; i < ArrangList1.Count; i++)
{
for (int j = 0; j < ArrangList1[i].Length; j++)
{
ArrangList1[i][1]; //the 1 here should be j
}
}

You can also use LINQ and one foreach loop:
// assuming ArrangList1 is List<string[]>
var query = from a in ArrangList1
from b in a
select b;
foreach (String s in query)
{
System.Console.Writeline(s);
}

Related

C# Pascal Triangle Code doesn't work - Logic correct

I've been trying to learn more about C#, and so I was doing a little practicing with Lists:
static void Main()
{
List<List<int>> a = new List<List<int>>();
List<int> temp = new List<int>();
temp.Add(1);
a.Add(temp);
for (int i = 0; i < 9; i++)
{
temp.Clear();
temp.Add(1);
for (int q = 0; q < a[i].Count-1; q++)
{
temp.Add(a[i][q] + a[i][q+1]);
}
temp.Add(1);
a.Add(temp);
}
foreach (var i in a[8])
Console.Write(i + " ");
Console.WriteLine();
}
I converted this to C++, and it works perfectly. However, in C#, a[i].Count is always 1. Even though after the first loop the size must be 2.
My only guess is that there's some major difference between C++'s Vector and C#'s List that I've apparently missed. Any ideas?
Here's the C++ code which works:
int main()
{
std::vector<std::vector<int>> a;
std::vector<int> b;
b.push_back(1);
a.push_back(b);
for (int i = 0; i < 9; i++)
{
b.clear();
b.push_back(1);
for (int q = 0; q < a[i].size()-1; q++)
{
b.push_back(a[i][q] + a[i][q+1]);
}
b.push_back(1);
a.push_back(b);
}
for (auto i : a[8])
{
std::cout << i << ' ';
}
}
Output for C++ Code:
1 8 28 56 70 56 28 8 1
Output For C# Code:
1 1
Any help is appreciated, thanks!
Look at your C# code a.Add(temp);. This temp variable is a reference type, so it will always add the same memory object.
To fix that, you can use LINQ to solve it:
a.Add(temp.ToList());. ToList() will generate a new object with different memory.
I have modified your code slightly, the main difference to not is, C# there are mainly 2
kind of types, one is a reference type and one is a value type.
List is a reference type.
In your code, you always clearing and adding numbers to the temp list.
that always points to the same object, so when you clear in the nth row, it's also clearing all the rows before it.
List<List<int>> a = new List<List<int>>();
a.Add(new List<int> { 1 });
for (int i = 0; i < 9; i++)
{
List<int> temp = new List<int>();
temp.Add(1);
for (int q = 0; q < a[i].Count - 1; q++)
{
temp.Add(a[i][q] + a[i][q + 1]);
}
temp.Add(1);
a.Add(temp);
}
foreach (var row in a)
{
foreach (var col in row)
{
Console.Write(col + " ");
}
Console.WriteLine();
}
Console.ReadKey();

Cannot convert from 'string' to 'system.collections.generic.list string'

I have the two list
nested list of string, and
list in string
In index list, I want to add linesOfContentwith a common value and in-between i want to add separate string ":".
For that i write a code, but, I face a problem "cannot convert from 'string' to 'system.collections.generic.list string'". How to solve this.
int common = 10;
List<List<string>> index = new List<List<string>>();
List<int> linesOfContent = new List<int>();
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 5; j++)
{
linesOfContent.Add(i+":"+common);
}
index.Add(linesOfContent);
}
Expected Output:
index[0][0] = 0:10
index[0][1] = 1:10
index[0][2] = 2:10
...
...
A List of Lists of string should contain Lists of string, not Lists of int.
int common = 10;
List<List<string>> index = new List<List<string>>();
List<string> linesOfContent = new List<string>();
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 5; j++)
{
linesOfContent.Add(i.ToString() +":"+common.ToString());
}
index.Add(linesOfContent);
}
Each item in your index list is a List<string>. When you try to add an item, it should be a List. However, you're trying to add a string to it, linesOfContent+":"+common is considered a string.
Solution:
Linq's Select Method (aka Projection) can be used to transform each element inside a sequence:
index.Add(linesOfContent.Select(x=> x.ToString() + ":" + common).ToList());
Be aware that the way you're constructing your loops results in some duplicate records.
Here's the code, without the foreach loops, instead it uses Enumerable.Range:
linesOfContent.AddRange(Enumerable.Range(0, 5).Select(i => i.ToString() + ":" + common.ToString()).ToArray());
index.Add(linesOfContent);

Searching two lists with nested loop

I'm trying to find an apartment number which is not already taken. So list<> is a list with already taken apartments and all<> is a list of all the apartments. so I try to iterate through them to find an apartment that is not already taken.
This does not work:
list<> // 4 indexes
all<> // 25 indexes
for (int i = 0;i < all.Count; i++)
{
for (int j = 0; j < list.Count; j++)
{
if (all[i].apartmentNr != list[j].apartmentNr)
{
apartmentNr = all[i].apartmentNr;
}
}
}
The problem is that you don't check all the list items so apartmentNr is set on first mismatch, but it's possibly taken on next list item. Thus you need to check all list items, before you can make a conclusion that it's free:
list<> // 4 indexes
all<> // 25 indexes
for (int i = 0;i < all.Count; i++)
{
bool taken = false;
for (int j = 0; j < list.Count; j++)
{
if (all[i].apartmentNr == list[j].apartmentNr)
{
taken = true;
break; // no need to check the rest
}
}
if (!taken) {
apartmentNr = all[i].apartmentNr;
break; // found first free
}
}
using System.Linq;
//availableApartments will contain all available apartments
var availableApartments = all.Except(list)
// Will get you the first item.
var freeApartment = availableApartments.FirstOrDefault()
Reference - Enumerable.Except

Iterate every combination of two elements in HashSet

How could I iterate through each combination of two elements in a HashSet once?
foreach (var elt1 in hashSet) {
foreach (var elt2 in hashSet) {
...
}
}
This would iterate the combinations of two but would iterate each combination TWICE. I'd like to do it once.
I think it's easy to do in Python. Is there any way to do it in C#?
Sample:
input hashSet: { 1, 2, 3, 4 }
iterate through: (1,2), (1,3), (1,4), (2,3), (2,4), (3,4)
There is no built-in method to do this in C#. Since HashSet<T> is not indexed *, you cannot do it with two loops either.
If this is a one-time deal, the simplest solution is to make two nested loops on the results of ToList() or ToArray(), like this:
var items = hashSet.ToList();
for (var i = 0 ; i != items.Count ; i++) {
var a = items[i];
for (var j = i+1 ; j != items.Count ; j++) {
var b = items[i];
}
}
If you are looking for something reusable, make an extension method on IEnumerable<T> that produces all pairs:
static IEnumerable<Tuple<T,T>> MakeAllPairs<T>(this IEnumerable<T> data) {
var items = data.ToList();
for (var i = 0 ; i != items.Count ; i++) {
var a = items[i];
for (var j = i+1 ; j != items.Count ; j++) {
var b = items[i];
yield return Tuple.Create(a, b);
}
}
}
Now you can iterate your pairs in a single loop:
foreach (var pair in hashSet.MakeAllPairs()) {
Console.WriteLine("{0} {1}", pair.Item1, pair.Item2);
}
* Technically, you could use ElementAt<T>(int) extension from Enumerable, but that would be very slow on large sets.
I misread the question originally. This is a new answer
This is what you want (if working index-based is an option). Explanation is below
string[] myArray = GetArray();
for (int i = 0; i < myArray.Length - 1; i++)
{
var element1 = myArray[i];
for(int j = i + 1; j < myArray.Length; j++)
{
var element2 = myArray[j];
Console.WriteLine("{0} {1}", element1, element2);
}
}
Explanation: Assume the following array:
Apple, Banana, Coconut, Zucchini
When i = 0 (Apple), j will be 1 (Banana), then 2 (Coconut), then 3 (Zucchini)
When i = 1 (Banana), j will be 2 (Coconut), then 3 (Zucchini).
And so on...
Basically, you are making sure element j is always ahead of element i. This means you've effectively removed half of the possibilities (where j would be before i), which is what you wanted.
Note: if you want to use sets of equal elements (Apple + Apple), the second for loop needs to change to:
for(int j = i; j < myArray.Length; j++) //notice j = i instead of i + 1
You can work with indexes directly on the HashSet.
Try this:
int int1, int2;
HashSet<int> hs = new HashSet<int>();
hs.Add(1);
hs.Add(2);
hs.Add(3);
for (int i = 0; i < hs.Count-1; i++) {
int1 = hs.ElementAt<int>(i);
for (int j = i + 1; j < hs.Count; j++)
{
int2 = hs.ElementAt<int>(j);
}
}
To return all permutations (viz (1,2) and (2,1)), you can cross join the set with itself using SelectMany:
var hashSet = new HashSet<int>{1,2,3,4,5,6,7,8};
foreach (var elt in hashSet.SelectMany(
x => hashSet.Select(y => new Tuple<int, int>(x, y))))
{
Debug.WriteLine("{0}-{1}", elt.Item1, elt.Item2);
}
Edit: If you just want the unique combinations (viz (1,2) but not (2,1)) then just add a filter only larger values during the cross join:
var hashSet = new HashSet<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
foreach (var elt in hashSet.SelectMany(
x => hashSet.Where(y => y >= x)
.Select(y => new Tuple<int, int>(x, y))))
{
Debug.WriteLine("{0}-{1}", elt.Item1, elt.Item2);
}

How to code for dynamic for-loop levels?

My problem is like this:
I have several lists need to be permuted, but the list numbers are unknowable. And every element numbers in every list are also unknowable. Sicne I would like to traverse all list element combination, like 1) pick A from list 1, A from list 2, A from list 3; 2) ick A from list 1, A from list 2, B from list 3 ... for ALL permutation.
I use nested for-loop to traverse, like if I have two lists, then:
for (int i = 0; i < list[0].EnergyParameters.ListEnergyLevelCandidates.Count; i++)
{
for (int j = 0; j < list[1].EnergyParameters.ListEnergyLevelCandidates.Count; j++)
{
// Do sth
}
}
If I have three lists, then:
for (int i = 0; i < list[0].EnergyParameters.ListEnergyLevelCandidates.Count; i++)
{
for (int j = 0; j < list[1].EnergyParameters.ListEnergyLevelCandidates.Count; j++)
{
for (int k = 0; k < list[2].EnergyParameters.ListEnergyLevelCandidates.Count; k++)
{
// Do sth
}
}
}
Because the list numbers are unknowable, so the nest numbers are unknowable, which means, I don't know how many levels of for-loop needs to be written.
Under this kind of circumstance, how can I write code for dynamic for-loop levels? I don't want to write 10 loops for 10 lists.
In case you do not know how many lists there are, you do not write nested loops: instead, you write recursion. At each level of the invocation you loop a single list, like this:
void AllCombos(List<string>[] lists, int level, string[] current) {
if (level == lists.Length) {
// Do somthing; items of current[] contain elements of the combination
} else {
foreach (var s in lists[level]) {
current[level] = s;
AllCombos(lists, level+1, current);
}
}
}
Call AllCombos as follows:
var lists = new List<string>[10];
for (int i = 0 ; i != 10 ; i++) {
lists[i] = PopulateMyList(i);
}
string[] current = new string[lists.Length];
AllCombos(lists, 0, current);

Categories