Looping through x number of arrays - c#

How do I loop through x number of arrays and visit all combinations of all cells in all of the arrays? The problem here is there can be x number of arrays of some items inside. For instance,
List<List<string>> _arrays = GetArrayInformation();
I want to compare all the string inside each array with all the other arrays and the strings inside of each array. Do I use while like
while(i < _arrays.Count)
Thanks for your answer. The answer seems simple but when you think about it is kind of tricky and hard.
Update:
Thanks for your answers. I can do this with a 3 arrays like
for(int i = 0; i < _arrays[0].Count; i++) {
for(int l = 0; l < _arrays[1].Count; l++) {
for(int m = 0; m < _arrays[2].Count; m++) {
string _hello = _arrays[0][i] + "|" + _arrays[1][l] + "|" + _arrays[2][m];
}
}
}
Because I have dynamic number of arrays, it gets tricky.

foreach(var array in _arrays)
{
foreach(var s in array)
{
foreach(var otherArray in _arrays)
{
if(otherArray == array) continue;
if(otherArray.Contains(s)) {} // not sure what you want to do
}
}
}
this will loop through every single string seeing if it is in any other array.... it's the straightforward approach, but not very efficient and will duplicate work.

There is no enough information is here
If you need to find elements that exists in few array You will use something like this:
var multipleWords = _arrays
.SelectMany(items => items.Distinct())
.GroupBy(item => item)
.Select(group => new {Item = group.Key, Count = group.Count()})
.Where(item => item.Count > 1)
.Select(item => item.Item)
.ToArray();
multipleWords will contain each word from the all these arrays that exists in two or more arrays

You could use a recursive search function.
public Search<T>(object o, string comparestring)
{
if(o is List<string>)
{
//Compare to your string
}
else
{
//Call this search function with the type of the object in the list.
//Will iterate through all of your strings recursively.
Type t = o.GetType().GetGenericArguments()[0];
foreach( object osub in (T)o)
Search<t>( ((t)o),comparestring)
}
}

Related

Need to get count of array items in my dictionary

I created a dictionary with the key of type string and the values of type string[]. i am having a hard time figuring out how to get the count of the array in the dict. so i know dict.count returns the number of dictionary pairs but not sure how to get the count of the array
Dictionary<string, string[]> csvFileNameSheetName = new Dictionary<string, string[]>();
i tried this but obviously wont work
for (int idx = 0; idx < csvFileNameSheetName.Values.Count; idx++)
what i need is something like csvFilenameSheetName.values.Values.count
Use Linq's SelectMany to put all the string[] items into a single enumeration:
csvFileNameSheetName.SelectMany(kvp=>kvp.Value).Count(); //using System.Linq
Or for better performance you can use Sum to add up the counts:
csvFileNameSheetName.Sum(kvp=>kvp.Value.Length); //using System.Linq
Use linq
int c = csvFileNameSheetName.Aggregate(0, (r, i) => r = r + i.Value.Count());
int count = csvFileNameSheetName.Aggregate(0, (r, kvp) => r = r + kvp.Value.Count());
OR
var count = 0;
foreach(var strArr in csvFileNameSheetName.Values)
{
count += strArr.Length;
}

Sorting a list in c# (custom defined sorting rules)

I have a list of string called choosedGroupList consisting of 5 items. Each item represents a group,
For example: L1andL4 means that L1 will be grouped with L4.
Another example: L1,L4andL5,L6 means that the group L1,L4 will be grouped with the group L5,L6
I am trying to sort this list to be like this:
L1andL4
L5andL6
L1,L4andL5,L6
L2andL1,L4,L5,L6
L3andL2,L1,L4,L5,L6
So I wrote this code to perform this task,
//sorting choosedGroupList
for (int k = 0; k < choosedGroupList.Count; k++)
{
for (int j = k + 1; j < choosedGroupList.Count; j++)
{
string[] parts = choosedGroupList[j].Split(new string[] { "and" }, StringSplitOptions.None);
if (parts[0] == choosedGroupList[k].Replace("and", ",") || parts[1] == choosedGroupList[k].Replace("and", ","))
{
string[] parts2 = choosedGroupList[k + 1].Split(new string[] { "and" }, StringSplitOptions.None);
//if (parts[0] != parts2[0] || parts[1] != parts2[1])
//{
String Temp = choosedGroupList[k + 1];
choosedGroupList[k + 1] = choosedGroupList[j];
choosedGroupList[j] = Temp;
//}
}
}
}
I have no exceptions in the code but, I do not get the desired results.
After executing the code this is the result:
L1andL4
L1,L4andL5,L6
L2andL1,L4,L5,L6
L5andL6
L3andL2,L1,L4,L5,L6
Assumption 1: you wish to sort first by number of 'L's then by the numbers following the 'L's.
The major issue in the code given is that you never check the length of the arrays, so L1,L4 will always sort before L5 because L1 sorts before L5.
If you split on 'and' separately from ',' and sort on length of the array split from ',' first before sorting on the contents of that array, then it should match your proposed sort order.
How about using a Dictionary?
public static Dictionary<string, int> YourDictionary()
{
Dictionary<string, int> returnDict = new Dictionary<string, int>();
returnDict.Add("L1andL4", 1);
returnDict.Add("L5andL6", 2);
returnDict.Add("L1,L4andL5,L6", 3);
returnDict.Add("L2andL1,L4,L5,L6", 4);
returnDict.Add("L3andL2,L1,L4,L5,L6", 5);
return returnDict;
}
Then iterate over the Dictionary:
var theDictionary = clsProdDesign.YourDictionary();
var items = from pair in theDictionary orderby pair.Value ascending select pair;
foreach (KeyValuePair<string, int> pair in items)
{
//do whatever
}

Sorting a list of 2D arrays

I'm trying to sort a list containing bool 2D arrays like below.
List<bool[,]>boolList;
bool[,] bool2DArray = {
{true,true,true,true},
{true,true,true,true},
{true,true,true,true}
};
I've been trying to sort the list they're in by the amount of true counts within each 2D Array.
After some research and looking over Stack Overflow I haven't been able to find a solution for this specific issue; many of the solutions I was able to find wouldn't work for me in this situation where I'm not comparing them directly, but rather the result of a calculation on them which led me to trying with a Lambada type solution which also failed but I think that might have been due to me not understanding how to implement it correctly.
Edit
Simple function I made for getting the count
int GetCount(bool[,]bool2DArray) {
int count = 0;
int rows = bool2DArray.GetUpperBound(0);
int columns = bool2DArray.GetUpperBound(1);
for (int x = 0; x <= rows; x++) {
for (int i = 0; i <= columns; i++) {
bool isTrue = bool2DArray[x, i];
if (isTrue) {
count++;
}
}
}
return count;
}
And this is the Lambada type solution I think is in the right direction but isn't valid.
List<bool[,]> sortedList = boolList.Sort((a,b) => (GetCount(a).CompareTo(GetCount(b))));
You'd first want to see how to easily work with the 2d array and count the number of trues in it. To do so for a single item, you could do something similar to what is found in this question: Fast way to convert a two dimensional array to a List ( one dimensional )
bool2DArray.Cast<bool>().Count(i => i)
Then wrapping that with OrderDescendingBy you get the desired result:
var collection = new List<bool[,]> { bool2DArray, ... };
var result = collection.OrderByDescending(item => item.Cast<bool>().Count(i => i));
I prefer this approach which I think is more readable and cover more usecases:
class Program
{
static void Main(string[] args)
{
List<bool[,]> boolList = new List<bool[,]>() {
new bool[,] {
{true,true,true,true},
{true,true,true,true},
{true,true,true,true}
},
new bool[,] {
{false,true,true,true},
{false,true,true,true},
{false,true,true,true}
}
};
boolList = OrderBoolArraysByBoolean(boolList, true);
}
private static List<bool[,]> OrderBoolArraysByBoolean(List<bool[,]> listOfArrays, bool value)
{
return listOfArrays.OrderByDescending(x => x.Cast<bool>().Count(i => i == value)).ToList();
}
}

Advanced Remove Array Duplicated

I have 3 arrays.
Array 1 = {1,1,1,1,2,2,3,3}
Array 2 = {a,a,a,a,e,e,b,b}
Array 3 = {z,z,z,z,z,z,z,z}
I would like to remove all duplicates from array 1 and also remove the same element at said duplicate in the other arrays to keep them all properly linked.
I know you can use .Distinct().ToArray() to do this for one array, but then the other arrays would not have the elements removed as well.
The result would look like this.
Array 1 = {1,2,3}
Array 2 = {a,e,b}
Array 3 = {z,z,z}
I'm guessing the only way to solve this would be the following.
For(int a = 0; a < Array1.count; a++) {
For(int b = a + 1; b < Array1.count; b++) {
if(Array1[a]==Array1[b]) {
Array1.RemoveAt(b);
Array2.RemoveAt(b);
Array3.RemoveAt(b);
}
}
}
Would be nice to find a simple predefined function however!
var distinctIndexes = array1
.Select((item, idx) => new { Item = item, Index = idx })
.GroupBy(p => p.Item)
.Select(grp => grp.First().Index);
var result1 = distinctIndexes.Select(i => array1[i]).ToArray();
var result2 = distinctIndexes.Select(i => array2[i]).ToArray();
var result3 = distinctIndexes.Select(i => array3[i]).ToArray();
Note this won't necessarily use the first unique element from the first array. If you need to do that you can calculate the indexes as
var distinctIndexes = array1
.Select((item, idx) => new { Item = item, Index = idx })
.Aggregate(new Dictionary<int, int>(), (dict, i) =>
{
if (! dict.ContainsKey(i.Item))
{
dict[i.Item] = i.Index;
}
return dict;
})
.Values;
You should consider what data structure you're using carefully. Is this "remove" operation likely to happen all at once? How often? (I'm not challenging your use of Array necessarily, just a general tip, but your scenario seems weird). Also, you did not explain if this is an index-based removal or an element based removal. If I was implementing this, I would be tempted to create a new Array and add all remaining elements to the new Array in a loop, ignoring the elements you want to remove. Then simply reassign the reference with '='. Of course, that depends on the maximum expected size of the Array, since a copy like I suggested would take up more memory (usually wouldn't be a problem).
I don't really know of a clean way to do what you're asking, but this is a generic example of doing what you asked?
static void RemoveDupes(ref Array a1, ref Array a2, ref Array a3)
{
Type a1t, a2t, a3t;
int newLength, ni, oi;
int[] indices;
a1t = a1.GetType().GetElementType();
a2t = a1.GetType().GetElementType();
a3t = a1.GetType().GetElementType();
Dictionary<object, List<int>> buckets = new Dictionary<object, List<int>>();
for (int i = 0; i < a1.Length; i++)
{
object val = a1.GetValue(i);
if (buckets.ContainsKey(val))
buckets[val].Add(i);
else
buckets.Add(val, new List<int> { i });
}
indices = buckets.Where(kvp => kvp.Value.Count > 1).SelectMany(kvp => kvp.Value.Skip(1)).OrderBy(i => i).ToArray();
newLength = a1.Length - indices.Length;
Array na1 = Array.CreateInstance(a1t, newLength);
Array na2 = Array.CreateInstance(a2t, newLength);
Array na3 = Array.CreateInstance(a3t, newLength);
oi = 0;
ni = 0;
for (int i = 0; i < indices.Length; i++)
{
while (oi < indices[i])
{
na1.SetValue(a1.GetValue(oi), ni);
na2.SetValue(a2.GetValue(oi), ni);
na3.SetValue(a3.GetValue(oi), ni);
oi++;
ni++;
}
oi++;
}
while (ni < newLength)
{
na1.SetValue(a1.GetValue(oi), ni);
na2.SetValue(a2.GetValue(oi), ni);
na3.SetValue(a3.GetValue(oi), ni);
oi++;
ni++;
}
a1 = na1;
a2 = na2;
a3 = na3;
}

Loop inside a array within a dictionary

Hi I have a quick question, which is the easiest way to loop inside an array that is within an object in a dictionary using C#?
The dictionary contain groups and groups have an array called tags, I have search for a tag and return a list of groups that contain that tag
I created a solution but it returns too many doubles when I apply it.
List<Programme> toReturn = new List<Programme>();
// might need to ask getprogramme service to do the iteriation and retun a value
foreach (Programme programme in programmes.Values)
{
if (message.Programme.Tags[0] != null)
{
int i;
int u;
foreach (KeyValuePair<string, Programme> entry in programmes)
{
// for (i = 0; i < message.Group.Tags.Length; i++)
for (i = 0; i < entry.Value.Tags.Length; i++)
//foreach (string i in message.Group.Tags)
{
for (u = 0; u < message.Programme.Tags.Length; u++)
{
// Compare the Name of the entry to the Name in the message (string comparison)
if (entry.Value.Tags[i].Equals(message.Programme.Tags[u]))
{
// If we found the group, set the return value and then break from the loop
toReturn.Add(programme);
break;
}
}
}
}
}
The easiest way is to use LINQ:
var res = groups.Where(g => g.Value.Any(t => t.Equals("search_tag")));

Categories