I want an array to contain strings, floats and ints that can be accessed via an index key.
I have an example in Lua how you would do but I don't know how you do it in C#
bookArray = [];
bookArray[1] =
{
Name = "Book 1";
Price = 50;
WPP = 374;
Pages = 42;
}
You may create a class and use List<MyClass>
class MyClass
{
public string Name {get;set;}
public double Price {get;set;}
public int Pages {get;set;}
}
Here is the list:
List<MyClass> values = new List<MyClass>();
Adding item
values.Add(new MyClass(){Name = "Book 1", Pages = 42, Price=50.0});
Insert at specific index:
values.Insert(0,new MyClass(){Name = "Book 2", Pages = 432, Price=10.0});
Retrieve at specific index:
MyClass theClass = values[1];
If you are ok with your inner type being immutable, you could do this:
var ar = new[] {
new { Name = "Book 1", Price = 50, WPP = 374, Pages = 42 },
new { Name = "Book 2", Price = 55, WPP = 220, Pages = 129 }
};
Which is about as close as you can come to the Lua definition
Related
I want to make one collection of three according to certain conditions (with LINQ). let's say I have a Class:
class Collection
{
public int id;
public string name;
public double weight;
}
Then I'm creating collections:
List<Collection> collection1 = new()
{
new Collection() { id = 11, name = "Abraham 1", weight = 1.1 },
new Collection() { id = 12, name = "Abraham 2", weight = 1.2 },
new Collection() { id = 13, name = "Abraham 3", weight = 1.3 },
};
List<Collection> collection2 = new()
{
new Collection() { id = 21, name = "Bill 1", weight = 2.1 },
new Collection() { id = 22, name = "Bill 2", weight = 2.2 },
new Collection() { id = 23, name = "Bill 3", weight = 2.3 },
};
List<Collection> collection3 = new()
{
new Collection() { id = 31, name = "David 1", weight = 3.1 },
new Collection() { id = 32, name = "David 2", weight = 3.2 },
new Collection() { id = 33, name = "David 3", weight = 3.3 },
};
TODO 1. Condition: get 1st column from 1st collection, 2nd column from 2nd collection, 3rd column from 3rd column. result should be:
{
new Collection() { id = 11, name = "Bill 1", weight = 3.1 },
new Collection() { id = 12, name = "Bill 2", weight = 3.2 },
new Collection() { id = 13, name = "Bill 3", weight = 3.1 }
}
TODO 2. Second case condition: get first elements from columns of all collections. result should be:
{
new Collection() { id = 11, name = "Abraham 1", weight = 1.1 },
new Collection() { id = 21, name = "Bill 1", weight = 2.1 },
new Collection() { id = 31, name = "David 1", weight = 3.1 }
}
Please help.
Using C# 10 and .Net 6, just use Enumerable.Zip:
var todo1 = collection1.Zip(collection2, collection3)
.Select(t => new Collection { id = t.First.id, name = t.Second.name, weight = t.Third.weight })
.ToList();
var todo2 = collection1.Zip(collection2, collection3)
.Select(t => new List<Collection> { t.First, t.Second, t.Third })
.First();
If you don't have the three argument Zip that returns a tuple, just roll your own, e.g. for Todo1:
var td1 = collection1.Zip(collection2, (c1, c2) => (c1, c2))
.Zip(collection3, (t12, c3) => (First: t12.c1, Second: t12.c2, Third: c3))
.Select(t => new Collection { id = t.First.id, name = t.Second.name, weight = t.Third.weight })
.ToList();
If you want to merge multiple collections into one collection using LINQ then do this:
List<Collection> result = collection1.Concat(collection2).OrderBy(x => x.id).ToList();
First, I would like to let you know that this is part of a homework exercise over Unit Testing.
What I need the test to do: I need to test that the list "actual" is equivalent to the list "expected".
This test fails and I receive this message:
CreatePurchasableList_IncludesExpectedItems
Source: GrandTotal.UnitTests.cs line 13
Duration: 30 ms
Message:
CollectionAssert.AreEquivalent failed. The expected collection contains 1 occurrence(s) of <GrandTotal_exercise.Appointment>. The actual collection contains 0 occurrence(s).
Stack Trace:
ProgramTests.CreatePurchasableList_IncludesExpectedItems() line 51
The method we want to test...
public static List<IPurchasable> CreatePurchasableList()
{
var appointment = new Appointment()
{
Name = "James",
StartDateTime = DateTime.Now.AddHours(1),
EndDateTime = DateTime.Now.AddHours(2),
Price = 100D
};
var book = new Book()
{
Title = "Welcome to Advanced C#",
Price = 50D,
TaxRate = 0.0825D,
ShippingRate = 5D
};
var snack = new Snack()
{
Price = 2D
};
var tshirt = new TShirt()
{
Size = "2X",
Price = 25D,
TaxRate = 0.0625D,
ShippingRate = 2
};
var items = new List<IPurchasable>();
items.Add(appointment);
items.Add(book);
items.Add(snack);
items.Add(tshirt);
return items;
}
TestMethod...
[TestMethod]
public void CreatePurchasableList_IncludesExpectedItems()
{
//Arrange
var appointment = new Appointment()
{
Name = "James",
StartDateTime = DateTime.Now.AddHours(1),
EndDateTime = DateTime.Now.AddHours(2),
Price = 100D
};
var book = new Book()
{
Title = "Welcome to Advanced C#",
Price = 50D,
TaxRate = 0.0825D,
ShippingRate = 5D
};
var snack = new Snack()
{
Price = 2D
};
var tshirt = new TShirt()
{
Size = "2X",
Price = 25D,
TaxRate = 0.0625D,
ShippingRate = 2
};
var expectedList = new List<IPurchasable>();
var purchasableListActual = Program.CreatePurchasableList();
//Act
expectedList.Add(appointment);
expectedList.Add(book);
expectedList.Add(snack);
expectedList.Add(tshirt);
//Assert
CollectionAssert.AreEquivalent(expectedList, purchasableListActual);
}
To be more clear I want to ensure that both tests include "appointment", "book", "snack", and "t-shirt".
I do not care what is inside of these objects or the order that they are in.
I'm working on a web application. I found this interesting https://github.com/mattosaurus/ChartJSCore. to use charts in my application.
The charts are working successfully in most pages. But in one page i have the following idea:
I have 3 properties (Appropriate, Inappropriate, NoInteraction) in my model all with type (int) and i need to keep it as integer to manipulate other functionalities in the application. Each property will be represented as one series in the chart and it should be list or array of 15 integer always.
Here is my properties in Session Model:
public int DayNumber { get; set; }
public int Appropriate { get; set; }
public int NotAppropriate { get; set; }
public int NoInteraction { get; set; }
Here is my Controller:
public IActionResult Details()
{
var result = _db.Session.ToList();
//I want this appropriateLine to be passed to GenerateLineChart method but whenever i tried i came up with an error of converting types.
var AppropriateLine = result.Select(x => x.Appropriate).ToList();
Chart lineChart = GenerateLineChart();
ViewData["LineChart"] = lineChart;
return View();
}
private static Chart GenerateLineChart()
{
Chart chart = new Chart();
chart.Type = Enums.ChartType.Line;
ChartJSCore.Models.Data data = new ChartJSCore.Models.Data();
data.Labels = new List<string>() { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" };
LineDataset AppropriateDataset = new LineDataset()
{
Label = "Appropriate Data Line",
Data = new List<double?>() { 2, 6, 2, 6, 2, 6 }, //Here i want this to be filled with data from AppropriateLine variable, it works for the fixed value only
Fill = "false",
LineTension = 0.1,
BackgroundColor = ChartColor.FromHexString("#FF6384"),
BorderColor = ChartColor.FromHexString("#FF6384"),
BorderCapStyle = "butt",
BorderDash = new List<int> { },
BorderDashOffset = 0.0,
BorderJoinStyle = "miter",
PointBorderColor = new List<ChartColor>() { ChartColor.FromHexString("#FF6384"), },
PointBackgroundColor = new List<ChartColor>() { ChartColor.FromHexString("#fff") },
PointBorderWidth = new List<int> { 1 },
PointHoverRadius = new List<int> { 5 },
PointHoverBackgroundColor = new List<ChartColor>() { ChartColor.FromHexString("#FF6384"), },
PointHoverBorderColor = new List<ChartColor>() { ChartColor.FromHexString("#FF6384"), },
PointHoverBorderWidth = new List<int> { 2 },
PointRadius = new List<int> { 1 },
PointHitRadius = new List<int> { 10 },
SpanGaps = false
};
data.Datasets = new List<Dataset>();
data.Datasets.Add(AppropriateDataset);
Options options = new Options()
{
Scales = new Scales()
};
Scales scales = new Scales()
{
YAxes = new List<Scale>()
{
new CartesianScale()
}
};
CartesianScale yAxes = new CartesianScale()
{
Ticks = new Tick()
};
Tick tick = new Tick()
{
Callback = "function(value, index, values) {return '' + value;}"
};
yAxes.Ticks = tick;
scales.YAxes = new List<Scale>() { yAxes };
options.Scales = scales;
chart.Options = options;
chart.Data = data;
return chart;
}
How can i implement this "Explicit Casting" of appropriateLine variable which is (int) before passing it to GenerateLineChart().
Note that i don't want to change Model properties type since many functions depend on it. Also, I cannot change Data type from List<double?> since many other problems solved by adding this.
I tried many casting solutions but none of them works for me such as:
(List<double?>)result.Select(x => x.Appropriate);
private static Chart GenerateLineChart((List<double?>)AppropriateLine)
I've read about "Convert all" method but not worked.
Any help is much appreciated,
Thanks in advance.
Based on what you mention, it seems that the data passed to GenerateLineChart will only be used for UI purposes. That is, this method can get an appropriate copy of the original data. If this is the case, then, the solution you attempted with
(List<double?>)result.Select(x => x.Appropriate)
was very close, but the cast needs to be done inside Select, i.e.
result.Select(x => (double?)x.Appropriate)
Here is a sketch of your code with that change
public IActionResult Details()
{
var result = _db.Session.ToList();
var AppropriateLine = result.Select(x => (double?)x.Appropriate).ToList();
var lineChart = GenerateLineChart(AppropriateLine);
// Rest or your code
}
private static Chart GenerateLineChart(IEnumerable<double?> data)
{
// Your code as is here ....
LineDataset AppropriateDataset = new LineDataset()
{
Data = data,
// Rest of your code
}
// ....
}
maybe you can check at the moment that you need the list if the number is double or int bool isInt = d == (int)d; and parse to use it only for that time on an aux.
I am programming in silverlight (c# .net)
lets say I have a list of type "data"
public class data
{
public string QUOTE_ID { get; set; }
public string EVENT_ACTION_CD { get; set; }
public string CUSTOMER_NAME { get; set; }
public string ADAPTIV_CODE { get; set; }
}
the problem is some of the data comes from 1 database and the other data comes from another, so right now i get the data in 2 steps - so i have something like this (using random numbers):
input1 = new List<data> //data return from database 1
//(the data is actually returned as a datable which i convert to a list
//to put to a datagrid, but the end result is shown below)
{
new data { QUOTE_ID = "1", EVENT_ACTION_CD = "2"},
new Project { QUOTE_ID = "2", EVENT_ACTION_CD = "4"},
new Project { QUOTE_ID = "3", EVENT_ACTION_CD = "5"}
};
input2 = new List<data> //data return from database 2
{
new data { QUOTE_ID = "1", CUSTOMER_NAME = "2", ADAPTIV_CODE ="5"},
new Project { QUOTE_ID = "2", CUSTOMER_NAME = "4", ADAPTIV_CODE = "5"},
new Project { QUOTE_ID = "3", CUSTOMER_NAME = "5", ADAPTIV_CODE = "7"}
};
so i should have 2 lists like
input1:
(1, 2, null, null
2, 4, null, null
3, 5, null, null)
and
input2:
(1, null, 2, 5
2, null, 4, 5
3. null, 5, 7)
how do i join them together to form one input list to become
(1, 2, 2, 5
2, 4, 4, 5
3, 5, 5, 7)
Use linq with a join operator.
See http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
var resultList = (from item in input1
join item2 in input2 on item2.QUOTE_ID equals input2.QUOTE_ID
let item.CUSTOMER_NAME = item2.CUSTOMER_NAME
let item.ADAPTIV_CODE = item2.ADAPTIV_CODE
select item).ToList();
A normal for loop would work for you:
for(int i = 0; i < input1.Count; i++){
if(input1[i].QUOTE_ID == null) input1[i].QUOTE_ID = input2[i].QUOTE_ID;
if(input1[i].EVENT_ACTION_CD == null) input1[i].EVENT_ACTION_CD = input2[i].EVENT_ACTION_CD;
if(input1[i].CUSTOMER_NAME == null) input1[i].CUSTOMER_NAME = input2[i].CUSTOMER_NAME;
if(input1[i].ADAPTIV_CODE == null) input1[i].ADAPTIV_CODE = input2[i].ADAPTIV_CODE;
}
The result will be saved into the input1. The code also supposes input1 and input2 have the same Count.
var input3 = input1.Join(
input2,
d1 => d1.QUOTE_ID,
d2 => d2.QUOTE_ID,
(d1, d2) => new data() {
QUOTE_ID = d1.QUOTE_ID,
EVENT_ACTION_CD = d1.EVENT_ACTION_CD,
CUSTOMER_NAME = d2.CUSTOMER_NAME,
ADAPTIV_CODE = d2.ADAPTIV_CODE
}
);
What does such an expression mean?
obj.DataSource = new[]
{
new {Text = "Silverlight", Count = 10, Link="/Tags/Silverlight" },
new {Text = "IIS 7", Count = 11, Link="http://iis.net" },
new {Text = "IE 8", Count = 12, Link="/Tags/IE8" },
new {Text = "C#", Count = 13, Link="/Tags/C#" },
new {Text = "Azure", Count = 13, Link="?Tag=Azure" }
};
Especially these lines: new {Text = "IIS 7"... }
How can I create an array like this manually to suit this DataSource.
First, let's reformat that code a little:
obj.DataSource = new[]
{
new { Text = "Silverlight", Count = 10, Link = "/Tags/Silverlight" },
new { Text = "IIS 7", Count = 11, Link = "http://iis.net" },
new { Text = "IE 8", Count = 12, Link = "/Tags/IE8" },
new { Text = "C#", Count = 13, Link = "/Tags/C#" },
new { Text = "Azure", Count = 13, Link = "?Tag=Azure" }
};
This does not look like a multi-dimensional array, but rather like an array of 5 objects. These objects inside the array are of an anonymous type, created and initialized using new { ... }.
Concerning your question how you can manually create such an array to suit the data source: you seem to be doing exactly that with the above code.
That's not a multidimensional array. That's an array of objects which have been created using object initializers with anonymous types.
Looks like an array of anonymous types.
http://msdn.microsoft.com/en-us/library/bb397696.aspx
Just to add: Anonymous types are converted by the compiler to a real object. So the code will be changed to something equivalent of this (MUCH simplified, only to show that the compiler will create an actual class):
internal sealed class AnonymousClass1
{
internal string Text { get; set; }
internal int Count { get; set; }
internal string Link { get; set; }
}
And your code will then be changed to:
obj.DataSource = new AnonymousClass1[]
{
new AnonymousClass1 {Text = "Silverlight", Count = 10, Link="/Tags/Silverlight" },
new AnonymousClass1 {Text = "IIS 7", Count = 11, Link="http://iis.net" },
new AnonymousClass1 {Text = "IE 8", Count = 12, Link="/Tags/IE8" },
new AnonymousClass1 {Text = "C#", Count = 13, Link="/Tags/C#" },
new AnonymousClass1 {Text = "Azure", Count = 13, Link="?Tag=Azure" }
};
In one of my programs, I have code like this (simplified!):
var myObjects = new []{
new { Id = Guid.NewGuid(), Title = "Some Title", Description = string.Empty },
new { Id = Guid.NewGuid(), Title = "Another Title", Description = string.Empty },
new { Id = Guid.NewGuid(), Title = "Number 3", Description = "Better than No2, but not much" }
}
foreach(var myObject in myObjects) {
DoSomeThingWith(myObject.Title);
}
This works because it is just another class (I even get IntelliSense) behind the scenes. The benefit is obviously that I just saved myself from creating a class for this object. In my example, all objects need to look the same as well. (Obviously, doing this for any public members would be a bad idea as the compiler might change the name of the anonymous class if you add/remove some)
It's making a new object array, containing a group of anonymous objects.
new {Text = "Azure", Count = 13, Link="?Tag=Azure" }
is not creating a hash like similar syntax in say php would, but rather real a real object with the properties Test, Count, and Link set.
A good primer for anonymous objects can be found here
You should be able to use the same syntax to create new structures like this, the property values do not have to be constants:
string text = "Azure";
int count = 13;
string link = "?Tag=Azure";
new {Text = text, Count = count, Link=link }
To return such an array from a function I used:
public object GetAnonymousArray()
{
var tbl = new List<object>();
while (___)
{
//fill array in cycle
tbl.Add(new {Text = someString, Count = someInt, Link = link});
}
return tbl;
}