Convert List<T> to Array in C# - c#

I have a list derived from
public class main
{
public list<myclass> data { get; set; }
}
public class myclass
{
public string variety { get; set; }
public string ordertype { get; set; }
public string producttype { get; set; }
}
Now I want to convert the List to return an array for VBA interop, how can I loop through my class in a single statement to convert all elements to array in one go. I have a few other classes that have a huge number of elements. I've tried the below code, but it's throwing out of bound error. I need to automatically loop through elements in myclass and assign it to array and so on. Is there any alternative/one-liner statement for this to convert the entire list to array.
string[] NamesArray = new string[list.Count];
string[] NamesArray2 = new string[] { };
for (int i = 0; i < NamesArray.Length; i++)
{
int idx = 0;
NamesArray[i] = bres.data[i].ToString();//here I am getting the myclass list not the elements inside the myclass.
foreach (var k in NamesArray[i].)
{
NamesArray2[idx++] = k.value.ToString();
}
}

Why don't you try doing:
myclass[] arr = data.ToArray();
Edit:
To return the array so it's visible from VBA, you'd need to have your class as ComVisible.
[ComVisible(true)]
public class main
{
public list<myclass> data { get; set; }
}
[ComVisible(true)]
public class myclass
{
public string variety { get; set; }
public string ordertype { get; set; }
public string producttype { get; set; }
}
[ComVisible(true)]
public myclass[] myclasses()
{
myclass[] arr = data.ToArray();
return arr;
}
#freeflow has a great reference link that you can use: https://analystcave.com/excel-use-c-sharp-in-excel-vba/

Related

What's the most efficient way of using AutoMapper to update / append to array?

I have an array of a class MyClassDTO that needs to be used to update items in the MyClass array:
public class MyClass
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
}
public class MyClassDTO
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
}
I was thinking using a dictionary to store the values from the DB and, then, iterate over the updated values and either update an existing value or create a new one. Something like this:
public void UpdateMyClassArray(IEnumerable<MyClassDTO> myClassDTOArray)
{
var currentValuesInDB = GetArray();
var myDictionary = new Dictionary<int, MyClass>();
foreach (var myClass in currentValuesInDB)
myDictionary.Add(myClass.Id, myClass);
var updatedMyClasses = myClassDTOArray
.Select(myClassDTO =>
{
if (myClassDTO.Id is null)
return Mapper.Map<MyClass>(myClassDTO);
int id = myClassDTO.Id.Value;
if (!myDictionary.ContainsKey(id))
return Mapper.Map<MyClass>(myClassDTO);
var storedMyClass = myDictionary[id];
return Mapper.Map(myClassDTO, storedMyClass);
});
SaveChanges(updatedMyClasses);
}
My question is: is there a better way of doing this? Does AutoMapper provide a built-in method for dealing with this case?

How to determine array in class?

I have a class like this:
class Zmogus
{
public string Vardas { get; set; }
public int Draugu_Kiekis { get; set; }
public string[] Draugas { get; set; }
public Zmogus(string vardas, int draugu_Kiekis, string[] draugas)
{
Vardas = vardas;
Draugu_Kiekis = draugu_Kiekis;
Draugas = draugas;
}
public Zmogus()
{
}
}
And i would like to know how to determine the size of it, because when i use it like this:
zmogus.Draugas[i] = parts[i+2];
It just shows me that the "Draugai" parameter is null.
Add the property:
public int DraugasLength{get {return this.Draugas.Length} set;}
or just use Draugas.Length. I think that behavior you are looking for is more like list than array - I would recommend using List from System.Collections.Generic instead of arrays.

Match names in list with elements in class

I wonder if there's any way to match the names in a list with the elements in a class:
I have a class:
public class exampleClass
{
public string name { get; set; }
public string value { get; set; }
}
and a List: List<exampleClass> EnfSist
So that's the way the list is made. Now I would like to know how to match or identify the string inside "name" from my list. To match this class:
tbl_sistematicas b = new tbl_sistematicas
{
ap_enf_id_enfermedad = Convert.ToInt32(EnfSist[0].value),
ap_pac_inicio = Convert.ToInt32(EnfSist[1].value),
ap_pac_inicio_periodo = Convert.ToInt32(2].value),
ap_pac_duracion = Convert.ToInt32(EnfSist[3].value),
ap_pac_duracion_periodo = Convert.ToInt32(EnfSist[4].value),
ap_pac_tratamiento = EnfSist[5].value
};
Once being able to match the same names I won't have to specify each index of every element in the list. The elements in the list have the same name as in the table. Not all elements of the class are being used.
I have something like this: tbl_sistematicas bh = EnfSist.FindAll(x => x.name == bh.?????? );
If I understand the question, you can do this using something like automapper or ValueInjector
An example using ValueInjector
void Main()
{
List<exampleClass> EnfSist = new List<exampleClass>();
EnfSist.Add(new exampleClass { name = "ap_enf_id_enfermedad", value = "12" });
EnfSist.Add(new exampleClass { name = "apap_pac_inicio" , value = "34" });
// etc
tbl_sistematicas b = new tbl_sistematicas();
b.InjectFrom<MyInjection>(EnfSist);
}
public class MyInjection : KnownSourceValueInjection<List<exampleClass>>
{
protected override void Inject(List<exampleClass> source, object target)
{
foreach(var entry in source)
{
var property = target.GetProps().GetByName(entry.name, true);
if (property != null)
property.SetValue(target, Convert.ChangeType(entry.value, property.PropertyType));
}
}
}
public class exampleClass
{
public string name { get; set; }
public string value { get; set; }
}
public class tbl_sistematicas
{
public int ap_enf_id_enfermedad { get; set; }
public int apap_pac_inicio { get; set; }
public int ap_pac_inicio_periodo { get; set; }
public int ap_pac_duracion { get; set; }
public int ap_pac_duracion_periodo { get; set; }
public string ap_pac_tratamiento { get; set; }
}
Note, this will throw an exception if the value can not be converted to an int

Populating a Classes Variables using values from a split string

So I have this code:
public class myClass
{
public string A { get; set; }
public string B{ get; set; }
//and so on
}
I want to add a constructor that takes a string input and have that constructor split the string on ','then use the split values to populate the class variables
What I Have Tried
I have tried to make a string with my variables values like so:
public void myVoid()
{
string s = "A,B,..etc";
string[] values = s.Split(',');
foreach (string item in values)
{
Console.WriteLine(item);
Console.ReadKey();
}
}
This returns my values one by one on each key press but this is just me getting my head around it.
So to clarify: I want to add a constructor that takes a string input and have that constructor split the string on ','then use the split values to populate the class variables
Is this what you want?
public class myClass
{
public myClass(string input)
{
var ar = input.Split(',');
if (ar.Length >= 2)
{
A = ar[0];
B = ar[1];
}
}
public string A { get; set; }
public string B{ get; set; }
//and so on
}
Use:
var myclass = new myClass("some,thing");
A simple approach would be:
public class myClass
{
public string A { get; set; }
public string B{ get; set; }
public myClass()
{
//default constructor
}
public myClass(string S)
{
string[] values = S.Split(',');
if (values.Length>=2)
{
this.A=values[0];
this.B=values[1];
}
}
}
However your goal is a bit fuzzy. E.g which value of splited string would appended on A and which in B?
Do you want this -
public class myClass
{
private string _a, _b;
public myClass(string args)
{
_a = args.Split(',')[0];
_b = args.Split(',')[1];
}
public string A { get { return _a; } set { _a = value; } }
public string B { get { return _b; } set { _b = value; } }
//and so on
}
public string A { get; set; }
public string B { get; set; }
public Sample(string strSplit) {
var values = strSplit.Split(',');
A = values[0];
B = values[1];
}
Sample dd = new Sample("James,Jonathan");
better use reflection

How to cast string list into a custom datatype?

Background: I'm trying to read from a csv file containing a mix of strings and doubles. I want to leave the strings as they are for searching and indexing purposes, but be able to perform data analysis on the double value within the list. I also don't want to read the entire csv file into memory before I separate it into it's different categories, so I'm trying to assign it to a list with a custom data type as it's read from the csv.
How can I cast that single list entry into a double and then add it to the list?
class data
{
public List<string> timefrom { get; set; }
public List<string> timeto { get; set; }
public List<string> type { get; set; }
public List<string> site { get; set; }
public List<string> box { get; set; }
public List<string> group { get; set; }
public List<string> sourcecopy { get; set; }
public List<string> destcopy { get; set; }
public List<string> gridid { get; set; }
public List<string> stat { get; set; }
public List<double> value { get; set; }
public List<string> unit { get; set; }
public List<string> peak { get; set; }
}
class Class1
{
public List<data>
WANtpfromSite,
WANtpbyCG,
IncomingWritesbyCG,
LinkUtilbyCG,
BoxUtil,
CompressionCPU,
ReplicationCPU,
CompressionRatio,
DeduplicationRatio,
IncomingWritesbyBox,
IncomingWritesbyBoxReplicating,
IObyBox,
IObyBoxReplicating,
PacketLoss,
LineLatency;
public void getDayData(string directory)
{
string[] fileEntries;
fileEntries = System.IO.Directory.GetFiles(directory + "/home/www/info/long_term_stats");
string filePath = fileEntries[0];
System.IO.StreamReader sr = new System.IO.StreamReader(filePath);
List<string> Line;
int row = 1;
while (!sr.EndOfStream)
{
//Splits the line read into a list of string values
Line = sr.ReadLine().Split(',').ToList<string>();
// Here I'll probably use a switch case to set the variable, but this is an example of what it should do.
if (Line[8] == "Wan Throughput from site")
{
//Here is where I'm having the problem - it can't implicitely convert the string list to a data list because
// of that single double value within the list. How would I go about explicitely converting the "Line"
//variable to a <data> type?
WANtpfromSite = List < data > datatype;
}
row++;
}
}
Well - the more I looked thorugh things it looks like a group of DataTable elements is what I needed. Instead of doing a list of lists, I just set up a datatable for each variabletype.

Categories