How to use two arrays in one foreach loop using C# - c#

How would I loop through two arays using a foreach loop?
I found this previously, but that's for PHP not c#
$images = array('image1', 'image2', ...);
$descriptions = array('description1', 'description2', ...);
foreach (array_combine($images, $descriptions) as $image => $desc) {
echo $image, $desc;
}
my thought is to have something like the following
string[] ValueA = {1,2,3}
string[] ValueB = (a,b,c}
foreach(something here from ValueA && ValueB)
{
methodNameHere(ValueA, ValueB); //method I am calling requires the two values
}

You will be Zip operation that come in .Net 4 in feature. This on link1 and link2 is description.
You will be right something like:
var alpha = new [] { A, B, C, D };
var day = new [] { "s", "s", "m", "t" };
var alphasAndDays = alpha.Zip(day, (n, w) => new { Alpha = n, Day = w });
foreach(var ad in alphasAndDays)
{
Console.WriteLine(aw.Alpha + aw.Day);
}

A simple reiteration can do that:
class Program
{
static void Main(string[] args)
{
string[] setA = new string[3] {"1", "2", "3"};
string[] setB = new string[3] { "a", "b", "c" };
foreach (string val1 in setA) {
foreach (string val2 in setB) {
Program test = new Program();
String printer = test.concatString(val1, val2);
Console.WriteLine(printer);
}
}
Console.ReadLine();
}
public string concatString(string value1, string value2) {
String value3 = value1 + value2;
return value3;
}
}

int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };
var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);
foreach (var item in numbersAndWords)
Console.WriteLine(item);
// This code produces the following output:
// 1 one
// 2 two
// 3 three

Related

Count occurrences of order dependent List<T> in List<List<T>>

There is a similar question that doesn't answer my question. --> Count number of element in List>
I have a list which contains sublists:
List<string> sublist1 = new List<string>() { "a", "b" };
List<string> sublist2 = new List<string>() { "a", "b" };
List<string> sublist3 = new List<string>() { "a", "c" };
Now I want to count the occurrences of each list.
a, b --> 2
a, c --> 1
I used distinct() from LINQ, but I got the output:
a, b --> 1
a, b --> 1
a, c --> 1
I assume that the hashcode is different.
Is there an alternative to distinct() which is looking at the list values instead?
I want to solve this in LINQ if possible.
Edit:
The order of list items has to be the same!
To use GroupBy() to do this, you will need a suitable IEqualityComparer<List<string>> that compares lists of strings. There is no built-in implementation, so you have to roll your own:
public sealed class StringListEqualityComparer : IEqualityComparer<List<string>>
{
public bool Equals(List<string> x, List<string> y)
{
if (ReferenceEquals(x, y))
return true;
if (x == null || y == null)
return false;
return x.SequenceEqual(y);
}
public int GetHashCode(List<string> strings)
{
int hash = 17;
foreach (var s in strings)
{
unchecked
{
hash = hash * 23 + s?.GetHashCode() ?? 0;
}
}
return hash;
}
}
Once you've got that, you can use it with GroupBy() as follows:
public static void Main()
{
var sublist1 = new List<string>{ "a", "b" };
var sublist2 = new List<string>{ "a", "b" };
var sublist3 = new List<string>{ "a", "c" };
var listOfLists = new List<List<string>> {sublist1, sublist2, sublist3};
var groups = listOfLists.GroupBy(item => item, new StringListEqualityComparer());
foreach (var group in groups)
{
Console.WriteLine($"Group: {string.Join(", ", group.Key)}, Count: {group.Count()}");
}
}
public JsonResult CountList(){
List<List<string>> d = new List<List<string>>(); //SuperList
d.Add(new List<string> { "a", "b" }); //List 1
d.Add(new List<string> { "a", "b" }); // List 2
d.Add(new List<string> { "a", "c" }); // List 3
d.Add(new List<string> { "a", "c", "z" }); //List 4
var listCount = from items in d
group items by items.Aggregate((a,b)=>a+""+b) into groups
select new { groups.Key, Count = groups.Count() };
return new JsonResult(listCount);
}
This will give the following Result as output in Post Man or Advanced REST Client
[{
"key": "ab",
"count": 2
},
{
"key": "ac",
"count": 1
},
{
"key": "acz",
"count": 1
}],
I think this will be helpful
var list = new List<List<string>>() { sublist1, sublist2, sublist3};
var result = list.GroupBy(x => string.Join(",",x)).ToDictionary(x => x.Key.Split(',').ToList(), x => x.Count());
You can try the below code:-
List<string> sublist1 = new List<string>() { "a", "b" };
List<string> sublist2 = new List<string>() { "a", "b" };
List<string> sublist3 = new List<string>() { "a", "c" };
List<List<string>> listOfLists = new List<List<string>> { sublist1, sublist2, sublist3 };
Dictionary<string, int> counterDictionary = new Dictionary<string, int>();
foreach (List<string> strList in listOfLists)
{
string concat = strList.Aggregate((s1, s2) => s1 + ", " + s2);
if (!counterDictionary.ContainsKey(concat))
counterDictionary.Add(concat, 1);
else
counterDictionary[concat] = counterDictionary[concat] + 1;
}
foreach (KeyValuePair<string, int> keyValue in counterDictionary)
{
Console.WriteLine(keyValue.Key + "=>" + keyValue.Value);
}
I think I will solve this with:
var equallists = list1.SequenceEqual(list2);
Therefore I compare distinct lists and lists with SequenceEquals() and counting them.
Better solutions welcome. :)

split a string array to a jagged object array

I want to make a string array with values of names and some numbers(which are strings)
i want to pass them into a function that will take the array and then split them into an object jagged array (1 array of strings and 1 array of ints)
the array is:
string[] str= { "toto", "the", "moto", "my", "friend","12","13","14","99","88"};
and the function looks like this:
public object[][] bloop (string[] bstr)
{
}
whats next?
Your scenario looks like bad design that can cause errors and performance issues. The better way is to change code for using generic List<> or something like that. But in your current problem you can use below code:
public object[][] bloop (string[] bstr)
{
var numbers = new List<int>();
var strings = new List<string>();
var result = new object[2][];
foreach(var str in bstr)
{
int number = 0;
if(int.TryParse(str, out number))
{
numbers.Add(number);
}
else
{
strings.Add(str);
}
}
result[0] = strings.ToArray();
result[1] = numbers.ToArray();
return result;
}
public static object[][] bloop(string[] bstr)
{
object[][] result = new object[2][] { new object[bstr.Length], new object[bstr.Length] };
int sFlag = 0, iFlag = 0, val;
foreach (string str in bstr)
if (int.TryParse(str, out val))
result[1][iFlag++] = val;
else
result[0][sFlag++] = str;
return result;
}
I agree that your requirement sounds odd and should be solved with a different approach. However, this will do what you want:
public T[][] Bloop<T>(T[] items)
{
if (items == null) throw new ArgumentNullException("items");
if (items.Length == 1) return new T[][] { items, new T[] { } };
int firstLength = (int) Math.Ceiling((double)items.Length / 2);
T[] firstPart = new T[firstLength];
Array.Copy(items, 0, firstPart, 0, firstLength);
int secondLength = (int)Math.Floor((double)items.Length / 2);
T[] secondPart = new T[secondLength];
Array.Copy(items, firstLength, secondPart, 0, secondLength);
return new T[][] { firstPart, secondPart };
}
Your sample:
string[] str= { "toto", "the", "moto", "my", "friend","12","13","14","99","88"};
string[][] result = Bloop(str);
If you need the second array as int[] you could use following:
int[] ints = Array.ConvertAll(result[1], int.Parse);
Linq solution.
You have two groups: first one has items that can be parsed to int and the second group contains all the others, so GroupBy looks quite naturally:
public Object[][] bloop(string[] bstr) {
if (null == bstr)
throw new ArgumentNullException("bstr");
int v;
return bstr
.GroupBy(x => int.TryParse(x, out v))
.OrderBy(chunk => chunk.Key) // let strings be the first
.Select(chunk => chunk.ToArray())
.ToArray();
}
Test:
string[] str = { "toto", "the", "moto", "my", "friend", "12", "13", "14", "99", "88" };
// toto, the, moto, my, friend
// 12, 13, 14, 99, 88
Console.Write(String.Join(Environment.NewLine,
bloop(str).Select(x => String.Join(", ", x))));

c# two string arrays print first array value to second array value expect 0

I want the output like this :
A=1
C=3
D=9
e=5
If second array value is 0 I don't want that value how to achieve this output in c#?
private static void Main(string[] args)
{
string[] a = new string[] { "a", "b", "c", "d" ,"e"};
string[] b = new string[] {1,0,3,0,5 };
foreach (string tmp in a)
{
bool existsInB = false;
foreach (string tmp2 in b)
{
if (tmp == tmp2)
{
existsInB = true;
break;
}
}
if (!existsInB)
{
Console.WriteLine(string.Format("{0} is not in b", tmp));
}
}
Console.ReadLine();
}
In that two arrays I want to print values like a=1,c=3,e=5, I don't want to print second array zero value. How do I achieve this?
I need a output in c#: a=1 c=3 e=5
I believe this will work for you
class Program
{
static void Main(string[] args)
{
string[] a = new string[] { "a", "b", "c", "d", "e" };
int[] b = new int[] { 1, 0, 3, 0, 5 };
for (int i = 0; i < a.Length; i++)
{
if (b[i] != 0)
Console.WriteLine(a[i] + "=" + b[i]);
}
Console.ReadLine();
}
}
Dictionary version (as per Matt Murdock's suggestion):
Dictionary<string, int> ab = new Dictionary<string, int>
{
{"a", 1},
{"b", 0},
{"c", 3},
{"d", 0},
{"e", 5}
};
foreach(var pair in ab)
{
if(pair.Value != 0)
Console.WriteLine(pair.Key + "=" + pair.Value);
}
The other answer by #interceptwind has already given a solution, this is just an alternative solution with Linq
string[] a = new string[] { "a", "b", "c", "d", "e" };
string[] b = new string[] { "1", "0", "3", "9", "5" };
var result = a.Zip(b, (strA, strB) => string.Format("{0}={1}", strA.ToUpper(), strB))
.Where(s => !s.Contains("=0"))
.ToArray();

Comparing two string arrays in C#

Say we have 5 string arrays as such:
string[] a = {"The","Big", "Ant"};
string[] b = {"Big","Ant","Ran"};
string[] c = {"The","Big","Ant"};
string[] d = {"No","Ants","Here"};
string[] e = {"The", "Big", "Ant", "Ran", "Too", "Far"};
Is there a method to compare these strings to each other without looping through them in C# such that only a and c would yield the boolean true? In other words, all elements must be equal and the array must be the same size? Again, without using a loop if possible.
You can use Linq:
bool areEqual = a.SequenceEqual(b);
Try using Enumerable.SequenceEqual:
var equal = Enumerable.SequenceEqual(a, b);
if you want to get array data that differ from another array you can try .Except
string[] array1 = { "aa", "bb", "cc" };
string[] array2 = { "aa" };
string[] DifferArray = array1.Except(array2).ToArray();
Output:
{"bb","cc"}
If you want to compare them all in one go:
string[] a = { "The", "Big", "Ant" };
string[] b = { "Big", "Ant", "Ran" };
string[] c = { "The", "Big", "Ant" };
string[] d = { "No", "Ants", "Here" };
string[] e = { "The", "Big", "Ant", "Ran", "Too", "Far" };
// Add the strings to an IEnumerable (just used List<T> here)
var strings = new List<string[]> { a, b, c, d, e };
// Find all string arrays which match the sequence in a list of string arrays
// that doesn't contain the original string array (by ref)
var eq = strings.Where(toCheck =>
strings.Where(x => x != toCheck)
.Any(y => y.SequenceEqual(toCheck))
);
Returns both matches (you could probably expand this to exclude items which already matched I suppose)
if (a.Length == d.Length)
{
var result = a.Except(d).ToArray();
if (result.Count() == 0)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("NO");
}
}
else
{
Console.WriteLine("NO");
}

compare two arrays and show count of characters

I have two arrays:
string[] array1 = {"a","b","c","d","e"}
string[] array1 = {"x","y","a","b","a"}
I want to print the result like this:
a = 3
b = 2
c = 1
d = 1
e = 1
x = 1
y = 1
z = 1
I can run a loop inside the loop and find this out but is there a better way to achieve the same result?
I want to do this in plain C# without using LINQ.
You can use LINQ to accomplish this:
var counts = array1.Concat(array2)
.GroupBy(v => v)
.Select(g => new { Value=g.Key, Number=g.Count() });
foreach(var item in counts.OrderBy(i => i.Value))
Console.WriteLine("{0} = {1}", item.Value, item.Number);
Given that you want to avoid using LINQ and the extension methods for some reason, you could build your own dictionary:
var counts = new Dictionary<string, int>();
foreach(string item in array1)
{
if (counts.ContainsKey(item))
counts[item]++;
else
counts[item] = 1;
}
foreach(string item in array2)
{
if (counts.ContainsKey(item))
counts[item]++;
else
counts[item] = 1;
}
// Print out counts
foreach(var kvp in counts)
Console.WriteLine("{0} = {1}", kvp.Key, kvp.Value);
Note that this doesn't sort the results - if you need them sorted, you'd have to do that as well.
You can use Concat, GroupBy and OrderByDescending:
var both = array1.Concat(array2);
var groups = both.GroupBy(s => s).OrderByDescending(g => g.Count());
Console.Write(
String.Join(
Environment.NewLine,
groups.Select(g => String.Format("{0} = {1}", g.Key, g.Count()))));
This looks like a job for Linq:
var charCounts = array1.Concat(array2)
.GroupBy(c=>c)
.Select(g=>new Tuple<char, int>(g.Key, g.Count());
.OrderBy(t=>t.Item1);
foreach(var result in charCounts)
Console.WriteLine(String.Format("{0} = {1}", t.Item1, t.Item2));
Read through the two arrays and put them into one dictionary. Keys are the members in the array like "a", "b", etc. Values are integers as count. So, if a key, exists, you increment the count; otherwise put the key into dictionary with a value as 1.
Well, most naive implementation based on type of string would be something like this:
class Program
{
static void Main(string[] args)
{
string[] array1 = {"a", "b", "c", "d", "e"};
string[] array2 = {"x", "y", "a", "b", "a"};
var histogram = new Dictionary<string, int>();
Fill(histogram, array1);
Fill(histogram, array2);
foreach (var p in histogram)
{
Console.WriteLine("{0}={1}",p.Key,p.Value);
}
}
private static void Fill(Dictionary<string, int> histogram, string[] a)
{
foreach (string s in a)
{
if (histogram.ContainsKey(s))
histogram[s] += 1;
else
histogram[s] = 1;
}
}
}
which is build dynamic histogram, print.
another simple approach is like this, but it's of worse readability:
static void Main(string[] args)
{
string[] array1 = {"a", "b", "c", "d", "e"};
string[] array2 = {"x", "y", "a", "b", "a"};
string [] concat = new string[array1.Length+array2.Length];
Array.Copy(array1,concat,array1.Length);
Array.Copy(array2,0,concat,array1.Length,array2.Length);
Array.Sort(concat);
int pos = 0;
while(pos<concat.Length)
{
var cur = concat[pos];
int count = 0;
while ( (pos<concat.Length) && (concat[pos]==cur))
{
pos += 1;
count += 1;
}
Console.WriteLine("{0}={1}",cur,count);
}
}
generally - concat, sort, histogram on sorted data.

Categories