I am new to c#, but not to programming. First of, thank you so much for your help!
I want a class or struct whichever is appropriate which has 3 variables. A string, and two datetimes.
I want to create a loop which stores new classes in a list.
Something like:
for each item in dataViewer
create new class
assign variables
store class in list
next
Thank you so much for your help
You can do this easily with LINQ:
var list = dataViewer
.Select(item => new YourClass
{
StringProperty = ...,
DateTimeProperty1 = ...,
DateTimeProperty2 = ...
})
.ToList();
It lets you state your intentions (create a list of YourClass objects from each item in dataViewer) without emphasizing the mechanics behind it (loops, etc.)
Edit: If you don't require a list, just a sequence, this also looks nice using the query syntax (same meaning):
var yourClasses =
from item in dataViewer
select new YourClass
{
StringProperty = ...,
DateTimeProperty1 = ...,
DateTimeProperty2 = ...
};
Maybe something like this
var list = new List<YourClass>();
foreach(var item in dataViewer) {
var cls = new YourClass();
// Assign variables here
// cls.Test = item.Test;
list.Add(cls);
}
Try this:
public class YourClass
{
public string YourString {get; set;}
public DateTime YourDate1 {get; set;}
public DateTime YourDate2 {get; set;}
public YourClass(string s, DateTime d1, DateTime d2)
{
YourString = s;
YourDate1 = d1;
YourDate2 = d2;
}
}
public List<YourClass> Read()
{
List<YourClass> list = new List<YourClass>();
foreach(var item in dataViewer)
list.Add(new YourClass(s,d1,d2)); // Read variables from item...
return list;
}
public class Appropriate
{
public string Value { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
IList<Appropriate> list = new List<Appropriate>();
foreach(var item in dataViewer) {
list.Add(new Appropriate() {
Value = item["value"],
Start = item["start"],
End = item["end"]
});
}
IList<Appropriate> list = new List<Appropriate>();
dataViewer.ToList().ForEach(i => list.Add(new Appropriate() {
Value = item["value"],
Start = item["start"],
End = item["end"]
});
public class Foo
{
public Foo(string name, DateTime dt1, DateTime dt2)
{
Name = name;
DT1 = dt1;
DT2 = dt2;
}
public string Name { get; set; }
public DateTime DT1 { get; set; }
public DateTime DT2 { get; set; }
}
public class Example
{
public List<Foo> example(DataView dataViewer)
{
var foos = new List<Foo>();
foreach(var data in dataViewer)
{
foos.Add(new Foo(data.Name, data.DT1, data.DT2);
}
return foos;
}
}
Related
Sorry but there is no code for this question... I hope thats ok.
So, I have a list of objects with two properties, DateTime and String.
As a matter of fact, DateTime is just date (insertDate), for example 2022-02-04T00:00:00+01:00.
String is of course some text, a lot of text :)
I have to compare the list with these two properties with another list of identical structure.
To be more clear, those are the data returned by the API, so I have to compare is there any differences between these two lists.
Do it like this (it will compare two lists based on element index , so
if your lists are unsorted you must sort them and then use these codes) :
public class YourClass
{
public DateTime DateTime { get; set; }
public string String { get; set; }
}
public class Program
{
static List<YourClass> list1 = new List<YourClass>
{
new YourClass { DateTime = DateTime.MinValue, String = "str1"},
new YourClass { DateTime = DateTime.Now.AddDays(1), String = "str2"},
new YourClass { DateTime = DateTime.Now.AddDays(2), String = "str3"}
};
static List<YourClass> list2 = new List<YourClass>
{
new YourClass { DateTime = DateTime.MinValue, String = "str1"},
new YourClass { DateTime = DateTime.Now.AddDays(-1), String = "2str"},
new YourClass { DateTime = DateTime.Now.AddDays(-2), String = "3str"}
};
static void Main(string[] args)
{
//a list of integer for storing different elements indexes
var differentElementsIndexes = new List<int>();
//check difference of these two list using for loop
for (int i = 0; i < list1.Count; i++)
{
if (list1.ElementAt(i).DateTime != list2.ElementAt(i).DateTime || list1.ElementAt(i).String != list2.ElementAt(i).String)
differentElementsIndexes.Add(i);
}
}
You can use a CustomComparator:
Given your base class for both lists:
public class BaseClass
{
public DateTime date { get; set; }
public string anyString { get; set; }
}
Define the custom comparer for it
public class BaseClassComparer : IEqualityComparer<BaseClass>
{
public bool Equals(BaseClass item1, BaseClass item2)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(item1, item2)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(item1, null) || Object.ReferenceEquals(item2, null))
return false;
//Check whether the required fields' properties are equal.
return (item1.date == item2.date) && (item1.anyString == item2.anyString);
}
public int GetHashCode(BaseClass item)
{
//Check whether the object is null
if (Object.ReferenceEquals(item, null)) return 0;
//Get hash code for the Date field if it is not null.
int hashItemDate = item.date == null ? 0 : item.date.GetHashCode();
//Get hash code for the string field.
int hashItemString = item.anyString.GetHashCode();
//Calculate the hash code for the item.
return hashItemDate ^ hashItemString;
}
}
Then you can use it as follows:
List<BaseClass> class1 = new List<BaseClass>();
List<BaseClass> class2 = new List<BaseClass>();
BaseClass item1 = new BaseClass() {date = DateTime.Now, anyString = "Hello"};
class1.Add(item1);
class2.Add(item1); //<-Equal till here
//class1.Add(item1); //<-uncomment for false
bool result = class1.SequenceEqual(class2, new BaseClassComparer());
I have an object like this -
public MyObject
{
public int Id { get; set; }
public string MyType { get; set; }
}
a list of those objects -
public List<MyObject> MyObjectList { get; set; }
and a list of string like this -
public List<string> MyTypeList { get; set; }
Using LINQ on MyObjectList, I want to create a list of MyObject removing any MyObject that has a MyObject.MyType that is in the MyTypeList.
Something like this (here are some unsuccessful attempts) -
List<MyObject> MyObjectListNEW = MyObjectList.Select(i => i.MyType).Except(MyTypeList).ToList();
List<MyObject> MyObjectListNEW = MyObjectList.Where(i => i.MyType.Except(MyTypeList));
This should work:
var MyObjectList = new List<MyObject>();
var MyTypeList = new List<string>();
var results = MyObjectList.Where(m => !MyTypeList.Any(t => m.MyType == t)).ToList();
I think it should be
var results = MyObjectList.Where(m => ! MyTypeList.Contains(m.MyType)).ToList();
try this
var results = MyObjectList.Where(m => !MyTypeList.Contains(m.MyType)).ToList();
As explained in https://learn.microsoft.com/de-de/visualstudio/code-quality/ca2227?view=vs-2019 I've got an object with a read only list like this:
public class MyClass {
public int id { get; set; }
public List<string> stringList { get; } = new List<string>;
}
But how can I initialize MyClass by adding data to stringList?
MyClass test = new MyClass(){
id = 1,
stringList = ???
}
You can use not very obvious syntax with collection initializers:
var x = new MyClass
{
id = 1,
stringList = {"as", "ddsd"} // will ADD "as", "ddsd" to stringList
};
Console.WriteLine(string.Join(", ", x.stringList)); // prints as, ddsd
Bur usual approach to handle readonly properties (until C# 9 is released with init only properties and records) is to pass initialization values in constructor.
You can pass the stringList as a parameter in the constructor and assign the property to the parameter:
public class MyClass {
public int id { get; set; }
public List<string> stringList { get; } = new List<string>();
public MyClass(List<string> stringList) {
this.stringList = stringList;
}
}
I have a array:-
private string[][] barValues = new string[][] { new string[]{ "1.9", "5.8", "4.8", "Since Inception", "24-Jan 2014 to 24 Jun 2014" },
new string[]{"1.2", "16.5","9.8", "Year to date","01-Apr 2014 to 24-Jun 2014" },
new string[]{"11.6","28.8","23.5","Last quarter","01-Jan to 24-Jun 2014"} };
I want to convert this array into my custom list :-
List<Portfolio> list = new List<Portfolio>();
I tried doing :-
List<Portfolio> list=myArray.Cast<Portfolio>().ToList();
But I get a error:-
System.InvalidCastException: Cannot cast from source type to
destination type.
How do I do this conversion?
You will need to use the Select operator and assign your array of strings to your Portfolio object. Something like this:
myArray.Select(array => new Portfolio { Field1 = array[0], Field2 = array[1] }).ToList()
There is no "magic" conversion from string[] to your class PortFolio, you have to do it manually.
This could work:
List<Portfolio> portFolioList = barValues
.Select(sArr => new Portfolio
{
Values = sArr.Take(3).Select(double.Parse).ToList(),
Name = sArr.Skip(3).First(),
TimeSpan = sArr.Last()
}).ToList();
If you have a class like this:
public class Portfolio
{
public List<double> Values { get; set; }
public string Name { get; set; }
public string TimeSpan { get; set; }
}
Convert Array to string try this way
string[] arr = ...
List<object> list= new List<object>(arr);
foreach(object obj in arr)
list.add(obj);
var converted = barValues.Select(a => new {Value1 = a[0], Value2= a[1]}).ToArray();
This gives you an array of anonymous objects. Just replace my anonymous constructor with your constructor of Portfolio. Lambda variable a is the array that contains the string values.
Create a constructor taking the items from barValues and iterator over those.
like:
class PortFolio()
{
PortFolio(string e1, string e2, string e3, string period, string date)
{
// Copy to properties.
}
...
}
Then in the code for copying:
foreach (var barValue in barValues)
{
list.Add(new PortFolio(barValue[0], barValue[1], barValue[2], barValue[3], barValue[4]); }
}
C# is a strongly typed language. There is no out of the box way to magically cast a bunch of string into an object.
A correct way to do what you want is to first add a constructor on your Portfolio class that takes an array of strings and assign its values to your instance properties:
class Portfolio
{
public string Value1 { get; set; }
public string Value2 { get; set; }
public string Value3 { get; set; }
public string Method { get; set; }
public string Period { get; set; }
public Portfolio(string[] values)
{
if (values != null)
{
this.Value1 = values.ElementAtOrDefault(0);
this.Value2 = values.ElementAtOrDefault(1);
this.Value3 = values.ElementAtOrDefault(2);
this.Method = values.ElementAtOrDefault(3);
this.Period = values.ElementAtOrDefault(4);
}
}
}
You can then use linq to build your list :
var portfoliosList = barValues.Select(values => new Portfolio(values)).ToList();
If required, you can do additional work in the constructor, for instance converting the values to decimal, the method to an Enum and the period as a couple of DateTime.
If you cannot modify the Portfolio class, because it's a third party component or out of your scope, you can create a factory class with a method containing that logic :
static class ProtfolioFactory
{
static public Portfolio BuildPortfolio(string[] values)
{
var portfolio = new Portfolio();
if (values != null)
{
portfolio.Value1 = values.ElementAtOrDefault(0);
portfolio.Value2 = values.ElementAtOrDefault(1);
portfolio.Value3 = values.ElementAtOrDefault(2);
portfolio.Method = values.ElementAtOrDefault(3);
portfolio.Period = values.ElementAtOrDefault(4);
}
return portfolio;
}
}
The linq query then becomes :
var list = barValues.Select(values => ProtfolioFactory.BuildPortfolio(values)).ToList();
My scenario :
I have an object, lets call it object1 which looks like this :
object1{
string commaSeparatedListOfIds;
DateTime time;
int passes;
...
irrelvant properties
...
}
What I wish to do is split commaSeparatedListOfIds for each id value, and save each one in it's own object (object2), with the relevant other properties.
object2{
int id;
DateTime time;
int passes;
}
This duplicates information, but for the method I want to write any other solution will be horrifically messy.
What I have tried is :
List<object2> newObjects = new List<object2>(object1.commaSeparatedListOfIds.Split(',').Select(
new object2{
id int.Parse,
time = object1.time
passes = object1.passes
}).ToList<object2>());
but this will not build.
Can anyone help me do what I wish as elegantly as possible please ? I realise it would be possible with two loops and some horrible code, but I know there's a nice looking solution out there somewhere! :)
I believe you want something like:
List<object2> newObjects = object1.commaSeparatedListOfIds.Split(',')
.Select(str =>
new object2
{
id = int.Parse(str),
time = object1.time,
passes = object1.passes
})
.ToList();
In query syntax(which i prefer when it comes to SelectMany):
var newObjects = from ob1 in object1
from strId in ob1.commaSeparatedListOfIds.Split(',')
select new object2(){
id = int.Parse(strId),
time = ob1.time,
passes = ob1.passes
};
List<object2> result = newObjects.ToList();
(mistakenly assumed that object1 is an IEnumerable<object1>)
public class O1
{
public string Ids { get; set; }
public DateTime Time { get; set; }
public int Passes { get; set; }
}
public class O2
{
public int Id { get; set; }
public DateTime Time { get; set; }
public int Passes { get; set; }
}
static void Main(string[] args)
{
var o1 = new O1();
o1.Ids = "1,2,3,4,5";
o1.Time = DateTime.Now;
o1.Passes = 42;
var results = o1.Ids.Split(',').Select(r => new O2 { Id = int.Parse(r), Time = o1.Time, Passes = o1.Passes });
foreach (var item in results)
{
Console.WriteLine("{0}: {1} {2}", item.Id, item.Time, item.Passes);
}
}
Something like that. Beware of just doing int.Parse(...), though, as you might have invalid data in your Id string.