adding an int value to multi array int list - c#

I got this multiarray list of integers that would look something like this:
List<List<int>> multiarray = new() {
new() { 8, 63 },
new() { 4, 2 },
new() { 0, -55 },
new() { 8, 57 },
new() { 2, -120},
new() { 8, 53 }
};
Now let's say I want to create it and add items using a variable, how will I do so?
I thought it would be as the following:
int value1 = 4
int value2 = 5
ListStat.Add(value1, value2);
But I get an error saying I cant overload using the method "add", any other command I should use?

(Alternate method for problem solving, without multi List, but it's longer)
//Helper
record ListStat (int value1, int value2)
static void Main(string[] args)
{
List<ListStat> lList = new List<ListStat>()
{
new ListStat(8,63),
new ListStat(4,2),
new ListStat(0,-55),
new ListStat(8,57)
};
lList.Add(new ListStat(0, 0)); //Adding values
Console.WriteLine($"({lList[0].value1};{lList[0].value2})"); //Ref to first element
//Ref for all element step by step in lList
foreach (ListStat singleItem in lList)
{
Console.WriteLine($"({singleItem.value1};{singleItem.value2})");
}
}

As your list has the element type of List<int> and not (int, int), you should NOT use multiarray.Add((value1, value2), but instead use the following:
int value1 = 4;
int value2 = 5;
multiarray.Add(new List<int> { value1, value2 });
or, even shorter using target-typed new-expressions:
multiarray.Add(new(){ value1, value2 });

If your sublists are known to have only 2 items, I would strongly advise you to use ValueTuple<...>s instead of List<int>. This not only enhances the readability of your code, but also reduces your application's memory footprint and execution speed, as less memory has to be allocated and no append/adding-operations have to be executed for the sublists.
The readability is enhanced, as items such as (1, 3) are automatically interpreted as ValueTuple<int, int>.
The resulting code should look as follows:
List<(int, int)> multiarray = new() {
(8, 63 ),
(4, 2 ),
(0, -55 ),
(8, 57 ),
(2, -120),
(8, 53 )
};
You may then add new items as follows (notice the extra parenthesis):
multiarray.Add((value1, value2));
You can display your items as follows:
foreach ((int, int) tuple in multiarray)
Console.WriteLine($"My list has the items ({tuple.Item1}, {tuple.Item2})");
or using the deconstruction-syntax:
foreach ((int value1, int value2) in multiarray)
Console.WriteLine($"My list has the items ({value1}, {value2})");
You may also might want to name your tuple elements:
List<(int a, int b)> multiarray = new() {
(8, 63),
(4, 2),
....
};
which allows you to use the following code:
int first = multiarray[0].a; // first tuple element of the first list item.

The List<T> class has an Add method that takes a single value of type T. When you have a List<List<T>> then the Add member takes a single value of type List<T>. You are trying to add two values of type T and the compiler doesn't know what to do with them.
If you want you code to work as is, then you can add an extension method to make it work.
Try this:
public static class MyListExtensions
{
public static void Add<T>(this List<List<T>> listList, params T[] items)
{
listList.Add(new List<T>(items));
}
}
Now your code works just fine:
List<List<int>> ListStat = new()
{
new() { 8, 63 },
new() { 4, 2 },
new() { 0, -55 },
new() { 8, 57 },
new() { 2, -120 },
new() { 8, 53 }
};
int value1 = 4
int value2 = 5
ListStat.Add(value1, value2);

You should create first your List<int> ListStat and then add to the List<List<int>> multiarray. For example:
var multiarray = new() {
new() { 8, 63 },
new() { 4, 2 },
new() { 0, -55 },
new() { 8, 57 },
new() { 2, -120},
new() { 8, 53 }
};
int value1 = 4;
int value2 = 5;
var ListStat = new(){ value1, value2};
multiarray.Add(ListStat);

Related

Can 2 arrays be merged into an array of structures with 2 fields using only LINQ?

I am wondering if two int arrays can theoretically be merged into a single array of structures using only LINQ, where each array going into its respective field?
So let's say we have 2 int arrays called numbers_raw and categories_raw, and class Record with 2 fields.
Using procedural code it looks like this:
class Record {
public int number;
public int category;
}
int[] numbers_raw = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 14, -4 };
int[] categories_raw = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2 };
var records = new List<Record>();
for (int ii = 0; ii < numbers_raw.Length; ii++) {
records.Add(new Record { number = numbers_raw[ii], category = categories_raw[ii] });
}
And if we had only 1 array and 1 field we could do it like this:
var records = numbers_raw.Select(x => new Record { number = x });
But I am not sure how to do it in such a way that both arrays are used, categories_raw going into the category field and numbers_raw goes into number field.
I am not sure if it is at all possible using LINQ.
Enumerable.Zip is what you need:
List<Record> records = numbers_raw
.Zip(categories_raw, (n, c) => new Record { number = n, category = c})
.ToList();
If one of both collections is larger, Zip takes all items until the common maximum count. For example, if one sequence has three elements and the other one has four, the result sequence will have only three elements.
This makes me wonder if there is a generic solution for any number of
arrays but I assume there isn't.
You're right, there is no ZipAll and it's not easy to build one. If you have 3 or 4 you could still use Zip, just concatenate them:
List<Record> records = numbers_raw
.Zip(categories_raw, (first, second) => (first, second))
.Zip(thirdSeq, (both, third) => new Record { number = both.first, category = both.second, thirdProperty = third})
.ToList();
or provide an extension method (this exists already with C#6 but only for 3):
public static class EnumerableExtensions
{
public static IEnumerable<TResult> Zip<TFirst, TSecond, TThird, TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
IEnumerable<TThird> third,
Func<TFirst, TSecond,
TThird, TResult> resultSelector)
{
using (IEnumerator<TFirst> e1 = first.GetEnumerator())
using (IEnumerator<TSecond> e2 = second.GetEnumerator())
using (IEnumerator<TThird> e3 = third.GetEnumerator())
while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext())
yield return resultSelector(e1.Current, e2.Current, e3.Current);
}
}
But these approches work just for a couple of sequences.
Yes, you can use Zip:
var records = numbers_raw.Zip(
categories_raw,
(x, y) => new Record {number = x, category = y})
.ToList();
You can use another version of .Select(element, index)
var records = numbers_raw.Select((x, index) =>
new Record {
number = numbers_raw[index],
category= categories_raw[index]
}).ToList();
Note: Here .Zip() is appropriate than .Select() version, I just shared alternate way to .Zip()
Why I said .Zip() is better than Select()here?
As #TimSchmelter said in his answer, Zip() takes all items until the common maximum count, but Select(element, index) will work only in case of numbers_raw.Count() > categories_raw.Count(). It will throw an Array out of bound exception if this condition failed.
If you desperate to use this solution, then always apply .Select() on the list which contains maximum elements.
Update:
I didn't know Zip actually comes with the same implementation, so I reworked the extension method slightly. As I got the problem with regular Select that it knows nothing about the index, so we can actually workaround this with the following extension:
public static IEnumerable<TResult> SelectByIndex<T1, TResult>(this IEnumerable<T1> sequence, Func<int, TResult> selector)
{
var baseArray = sequence.ToArray();
for (int i = 0; i < baseArray.Length; i++)
{
TResult result;
try
{
result = selector(i);
}
catch (IndexOutOfRangeException)
{
yield break;
}
yield return result;
}
}
And then use it like this:
var result = numbers_int.SelectByIndex(i => new Record {number = numbers_int[i], category = categories_raw[i]});
Old answer:
While Zip is good for the simple solution, you can write your own with the LINQ extension methods.
Let's assume your record class has different types of fields:
class Record
{
public int number;
public string category;
}
Then you can define your own LINQ expression for such case:
public static class LinqExtensions
{
public static IEnumerable<TResult> Merge<T1, T2, TResult>(this IEnumerable<T1> sequence, IEnumerable<T2> other, Func<T1, T2, TResult> selector)
{
using var sequenceEnumerator = sequence.GetEnumerator();
using var otherEnumerator = other.GetEnumerator();
while (sequenceEnumerator.MoveNext() && otherEnumerator.MoveNext())
{
yield return selector(sequenceEnumerator.Current, otherEnumerator.Current);
}
}
}
And use it like this:
int[] numbers_int = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 14, -4 };
string[] categories_str = { "0", "0", "0", "0", "1", "1", "1", "1", "2", "2", "2"};
var result = numbers_int.Merge(categories_str, (i, s) => new Record {number = i, category = s});
This will give you the flexibility of defining your own generic methods for any situtation.
int[] numbers_raw = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 14, -4 };
int[] categories_raw = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2 };
var records = numbers_raw.Select(delegate(int value, int index)
{
return new Record() {category = categories_raw[index], number = numbers_raw[index]};
});

c# can predefined values sum up to a certain value

I have a list with predefined int values.
List<int> values = new List<int>() { 1, 5, 7, 12, 20 };
I would like to know if a certain value can be summed up by the values in my list.
public bool canBeSummed(int value)
{
//Can any of the values in values sum up to value?
}
How can i solve this?
You would have to get all combinations from the list ant than check if sum is equal to value provided:
Create Extension method to get Combinations from the list of values (this will help you later)
public static class ExttensionMethods
{
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c)));
}
}
Next create method:
public bool CanBeSummed(int value, int[] values)
{
if (values.Contains(value)) return true;
var smaller = values.Where(x => x <= value);
if (!smaller.Any()) return false; // all values are bigger than value
var count = smaller.Count();
if (count == 1) return false; // Only 1 number and it is not value since values.Contains(value) has to be false
// Check all combinations from items (from 2 to x items where x is number of items in smaller list
return Enumerable.Range(2, count - 1).Any(x => smaller.Combinations(x).Any(c => c.Sum() == value));
}
Test:
public static object[] SumTest =
{
new object[] {6, true, new int[] {1, 5, 7, 12, 20}},
new object[] {37, true, new int[] {1, 5, 7, 12, 20}},
new object[] {9, false, new int[] {1, 5, 7, 12, 20}}
};
[TestCaseSource("SumTest")]
public void Test(int value, bool expectedResult, int[] values)
{
Assert.AreEqual(expectedResult, CanBeSummed(value, values));
}

Initialize and return jagged array in one line

Currently I am doing this
public int[][] SomeMethod()
{
if (SomeCondition)
{
var result = new int[0][];
result[0] = new int[0];
return result;
}
// Other code,
}
Now in this I only want to return empty jagged array of [0][0]. Is it possible to reduce three lines to one. I want to achieve something like this
public int[][] SomeMethod()
{
if (SomeCondition)
{
return new int[0][0];
}
// Other code,
}
Is it possible?
In the general case, you can let the compiler count elements for you:
public int[][] JaggedInts()
{
return new int[][] { new[] { 1, 2, 3 }, new[] { 4, 5, 6 }, new[] { 7, 8, 9, 10 } };
}
Or if you want it very compact, use an expression body:
public int[][] JaggedInts() => new int[][] { new[] { 1, 2, 3 }, new[] { 4, 5, 6 }, new[] { 7, 8, 9, 10 } };
Since you asked for an empty jagged array, you already had it:
var result = new int[0][];
The next line in your question will throw a run-time exception, since [0] is the first element in an array, which must be 1 or or more elements in length;
result[0] = new int[0]; // thows IndexOutOfRangeException: Index was outside the bounds of the array.
Here is what I think you asked for in just one line:
public int[][] Empty() => new int[0][];
Please have a look here https://stackoverflow.com/a/1739058/586754 and below.
You will need to create some helper functions and then it becomes a one-liner.
(Also was looking for a 1-line-solution.)
by returning value of jagged array its give you some ambiguous result,if you want to return some specific value of some specific index of jagged array you can return by assigning them to variable
public static int aaa()
{
int[][] a = new int[2][] { new int[] { 1, 2 }, new int[] { 3, 4 } };
int abbb=a[0][0];
Console.WriteLine(a[0][0]);
return abbb;
}
the following code will return 1 becoz this is first element of jagged array

How to easily initialize a list of Tuples?

I love tuples. They allow you to quickly group relevant information together without having to write a struct or class for it. This is very useful while refactoring very localized code.
Initializing a list of them however seems a bit redundant.
var tupleList = new List<Tuple<int, string>>
{
Tuple.Create( 1, "cow" ),
Tuple.Create( 5, "chickens" ),
Tuple.Create( 1, "airplane" )
};
Isn't there a better way? I would love a solution along the lines of the Dictionary initializer.
Dictionary<int, string> students = new Dictionary<int, string>()
{
{ 111, "bleh" },
{ 112, "bloeh" },
{ 113, "blah" }
};
Can't we use a similar syntax?
c# 7.0 lets you do this:
var tupleList = new List<(int, string)>
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
If you don't need a List, but just an array, you can do:
var tupleList = new(int, string)[]
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
And if you don't like "Item1" and "Item2", you can do:
var tupleList = new List<(int Index, string Name)>
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
or for an array:
var tupleList = new (int Index, string Name)[]
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
which lets you do: tupleList[0].Index and tupleList[0].Name
Framework 4.6.2 and below
You must install System.ValueTuple from the Nuget Package Manager.
Framework 4.7 and above
It is built into the framework. Do not install System.ValueTuple. In fact, remove it and delete it from the bin directory.
note: In real life, I wouldn't be able to choose between cow, chickens or airplane. I would be really torn.
Yes! This is possible.
The { } syntax of the collection initializer works on any IEnumerable
type which has an Add method with the correct amount of arguments.
Without bothering how that works under the covers, that means you can
simply extend from List<T>, add a custom Add method to initialize your
T, and you are done!
public class TupleList<T1, T2> : List<Tuple<T1, T2>>
{
public void Add( T1 item, T2 item2 )
{
Add( new Tuple<T1, T2>( item, item2 ) );
}
}
This allows you to do the following:
var groceryList = new TupleList<int, string>
{
{ 1, "kiwi" },
{ 5, "apples" },
{ 3, "potatoes" },
{ 1, "tomato" }
};
C# 6 adds a new feature just for this: extension Add methods. This has always been possible for VB.net but is now available in C#.
Now you don't have to add Add() methods to your classes directly, you can implement them as extension methods. When extending any enumerable type with an Add() method, you'll be able to use it in collection initializer expressions. So you don't have to derive from lists explicitly anymore (as mentioned in another answer), you can simply extend it.
public static class TupleListExtensions
{
public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
T1 item1, T2 item2)
{
list.Add(Tuple.Create(item1, item2));
}
public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> list,
T1 item1, T2 item2, T3 item3)
{
list.Add(Tuple.Create(item1, item2, item3));
}
// and so on...
}
This will allow you to do this on any class that implements IList<>:
var numbers = new List<Tuple<int, string>>
{
{ 1, "one" },
{ 2, "two" },
{ 3, "three" },
{ 4, "four" },
{ 5, "five" },
};
var points = new ObservableCollection<Tuple<double, double, double>>
{
{ 0, 0, 0 },
{ 1, 2, 3 },
{ -4, -2, 42 },
};
Of course you're not restricted to extending collections of tuples, it can be for collections of any specific type you want the special syntax for.
public static class BigIntegerListExtensions
{
public static void Add(this IList<BigInteger> list,
params byte[] value)
{
list.Add(new BigInteger(value));
}
public static void Add(this IList<BigInteger> list,
string value)
{
list.Add(BigInteger.Parse(value));
}
}
var bigNumbers = new List<BigInteger>
{
new BigInteger(1), // constructor BigInteger(int)
2222222222L, // implicit operator BigInteger(long)
3333333333UL, // implicit operator BigInteger(ulong)
{ 4, 4, 4, 4, 4, 4, 4, 4 }, // extension Add(byte[])
"55555555555555555555555555555555555555", // extension Add(string)
};
C# 7 will be adding in support for tuples built into the language, though they will be of a different type (System.ValueTuple instead). So to it would be good to add overloads for value tuples so you have the option to use them as well. Unfortunately, there are no implicit conversions defined between the two.
public static class ValueTupleListExtensions
{
public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
ValueTuple<T1, T2> item) => list.Add(item.ToTuple());
}
This way the list initialization will look even nicer.
var points = new List<Tuple<int, int, int>>
{
(0, 0, 0),
(1, 2, 3),
(-1, 12, -73),
};
But instead of going through all this trouble, it might just be better to switch to using ValueTuple exclusively.
var points = new List<(int, int, int)>
{
(0, 0, 0),
(1, 2, 3),
(-1, 12, -73),
};
You can do this by calling the constructor each time with is slightly better
var tupleList = new List<Tuple<int, string>>
{
new Tuple<int, string>(1, "cow" ),
new Tuple<int, string>( 5, "chickens" ),
new Tuple<int, string>( 1, "airplane" )
};
Old question, but this is what I typically do to make things a bit more readable:
Func<int, string, Tuple<int, string>> tc = Tuple.Create;
var tupleList = new List<Tuple<int, string>>
{
tc( 1, "cow" ),
tc( 5, "chickens" ),
tc( 1, "airplane" )
};
Super Duper Old I know but I would add my piece on using Linq and continuation lambdas on methods with using C# 7. I try to use named tuples as replacements for DTOs and anonymous projections when reused in a class. Yes for mocking and testing you still need classes but doing things inline and passing around in a class is nice to have this newer option IMHO. You can instantiate them from
Direct Instantiation
var items = new List<(int Id, string Name)> { (1, "Me"), (2, "You")};
Off of an existing collection, and now you can return well typed tuples similar to how anonymous projections used to be done.
public class Hold
{
public int Id { get; set; }
public string Name { get; set; }
}
//In some method or main console app:
var holds = new List<Hold> { new Hold { Id = 1, Name = "Me" }, new Hold { Id = 2, Name = "You" } };
var anonymousProjections = holds.Select(x => new { SomeNewId = x.Id, SomeNewName = x.Name });
var namedTuples = holds.Select(x => (TupleId: x.Id, TupleName: x.Name));
Reuse the tuples later with grouping methods or use a method to construct them inline in other logic:
//Assuming holder class above making 'holds' object
public (int Id, string Name) ReturnNamedTuple(int id, string name) => (id, name);
public static List<(int Id, string Name)> ReturnNamedTuplesFromHolder(List<Hold> holds) => holds.Select(x => (x.Id, x.Name)).ToList();
public static void DoSomethingWithNamedTuplesInput(List<(int id, string name)> inputs) => inputs.ForEach(x => Console.WriteLine($"Doing work with {x.id} for {x.name}"));
var namedTuples2 = holds.Select(x => ReturnNamedTuple(x.Id, x.Name));
var namedTuples3 = ReturnNamedTuplesFromHolder(holds);
DoSomethingWithNamedTuplesInput(namedTuples.ToList());
One technique I think is a little easier and that hasn't been mentioned before here:
var asdf = new [] {
(Age: 1, Name: "cow"),
(Age: 2, Name: "bird")
}.ToList();
I think that's a little cleaner than:
var asdf = new List<Tuple<int, string>> {
(Age: 1, Name: "cow"),
(Age: 2, Name: "bird")
};
var colors = new[]
{
new { value = Color.White, name = "White" },
new { value = Color.Silver, name = "Silver" },
new { value = Color.Gray, name = "Gray" },
new { value = Color.Black, name = "Black" },
new { value = Color.Red, name = "Red" },
new { value = Color.Maroon, name = "Maroon" },
new { value = Color.Yellow, name = "Yellow" },
new { value = Color.Olive, name = "Olive" },
new { value = Color.Lime, name = "Lime" },
new { value = Color.Green, name = "Green" },
new { value = Color.Aqua, name = "Aqua" },
new { value = Color.Teal, name = "Teal" },
new { value = Color.Blue, name = "Blue" },
new { value = Color.Navy, name = "Navy" },
new { value = Color.Pink, name = "Pink" },
new { value = Color.Fuchsia, name = "Fuchsia" },
new { value = Color.Purple, name = "Purple" }
};
foreach (var color in colors)
{
stackLayout.Children.Add(
new Label
{
Text = color.name,
TextColor = color.value,
});
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
}
this is a Tuple<Color, string>

Is there a concise way to check if an int variable is equal to a series of ints? | C#

Rather than something like this:
switch (id) {
case 2:
case 5:
case 11:
case 15:
...
}
Is there a concise way to check if an int variable is equal to any one of a series of integers? Maybe something like if (id == {2|5|11|15}) ...?
You could put all the ints into a HashSet and do a contains.
Hashset<int> ids = new HashSet<int>() {...initialize...};
if(ids.Contains(id)){
...
}
if((new List<int> { 2, 5, 11, 15}).Contains(id))
But you probably don't want to create a new List instance every time, so it would be better to create it in the constructor of your class.
You could try:
List<int> ints = new List<int> {2, 5, 11, 15};
if (ints.Contains(id))
{
}
Though it might be slower than doing the switch.
However, it does have the advantage that (assuming that you initialise the list from data) you can use this to check on any list of integer values and aren't constrained to hard coded values.
If your goal is to be concise.
//
(new []{2, 5, 11, 15}).Contains(id)
//
If you want to be fast probably stick with the switch.
I think I like the HashSet though.
Perhaps a solution using LINQ:
List<int> ints = new List<int> {2, 5, 11, 15};
void Search(int s) {
int result = ints.Where(x => x == s).FirstOrDefault();
}
You can do something like this:
bool exist = List.Init(6, 8, 2, 9, 12).Contains(8);
foreach (int i in List.Init(6, 8, 2, 9, 12))
{
Console.WriteLine(i.ToString());
}
public class List : IEnumerable<int>
{
private int[] _values;
public List(params int[] values)
{
_values = values;
}
public static List Init(params int[] values)
{
return new List(values);
}
public IEnumerator<int> GetEnumerator()
{
foreach (int value in _values)
{
yield return value;
}
}
public bool Contains(int value)
{
return Array.IndexOf(_values, value) > -1;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

Categories

Resources