I have these classes:
class Car {
String carId;
int yearOfManufacture;
//constructor, fromJson, toJson ...
}
class CarsByYears {
int yearOfManufacture;
List<Car> carList;
//constructor, fromJson, toJson ...
}
And I need to generate a data structure like this based on the given car list only:
List<CarsByYears>
So I get a List<Car> list, and I need to create a List<CarsByYears> list from that. So I need to group the cars by years.
For example I have a List<Car> list which contains these:
Car(1, 1990)
Car(2, 2001)
Car(3, 1990)
I need to create a List<CarsByYears>, which contains 2 CarsByYears object:
The first one is like: yearOfManufacture = 1990 and the carList contains the 1st and the 3rd car object, and the other CarsByYears is contains the 2nd Car object in its carList, and the yearOfManufacture = 2001
How can I do that?
You can use the groupBy function provided by the collection package (which creates a map from a List groping it using a common value as key) and then map the Map entries.
class Car {
final String carId;
final int yearOfManufacture;
Car(this.carId, this.yearOfManufacture);
#override
String toString() => 'Car($carId)';
// Use your constructor and methods
}
class CarsByYears {
final int yearOfManufacture;
final List<Car> carList;
CarsByYears(this.yearOfManufacture, this.carList);
#override
String toString() => 'Year: $yearOfManufacture, Cars: $carList';
// Use your constructor and methods
}
void main() {
var cars = [
Car('1', 2000),
Car('2', 2002),
Car('3', 2000),
Car('4', 2002),
Car('1', 2005)
];
var carsByYear = groupBy<Car, int>(cars, (e) => e.yearOfManufacture)
.entries
.map((e) => CarsByYears(e.key, e.value))
.toList();
print(carsByYear); //Output: [Year: 2000, Cars: [Car(1), Car(3)], Year: 2002, Cars: [Car(2), Car(4)], Year: 2005, Cars: [Car(1)]]
}
Related
I have a Flutter app in which I make an http request, which brings me json data. Afer formatting it with a package I get a list of lists of dynamic type. Here´s what it looks like:
[[2016-04-01, 85.5254], [2016-05-01, 89.1118], [2016-06-01, 91.8528], [2016-07-01, 93.7328], [2016-08-01, 93.9221], [2016-09-01, 95.0014], [2016-10-01, 97.2428], [2016-11-01, 98.8166]]
So I created a class named IpcData, which recieves a String and a double.
class IpcData {
final String date;
final double value;
IpcData(this.date, this.value);
}
So we could guess that an IpcData instance would look like the following:
IpcData(2016-08-01, 93.9221)
I can´t figure out how, but I´d like to have a method that using the information from the List<List<dynamic>> to return a List<IpcData>, that would looke like:
[IpcData(2016-08-01, 93.9221), IpcData(2016-08-01, 93.9221), IpcData(2016-08-01, 93.9221),]
You can use .map function on the original list to construct the new one. Something like this.
class IpcData {
final String date;
final double value;
IpcData(this.date, this.value);
#override
String toString() {
return '$date -> $value';
}
}
void main() {
List<List<dynamic>> initList = [
['2016-04-01', 85.5254], ['2016-05-01', 89.1118], ['2016-06-01', 91.8528],
['2016-07-01', 93.7328], ['2016-08-01', 93.9221], ['2016-09-01', 95.0014],
['2016-10-01', 97.2428], ['2016-11-01', 98.8166], ['2016-12-01', 99.8166]
];
List<IpcData> ipcList = initList.map((e) => IpcData(e[0], e[1])).toList();
print(ipcList);
}
I am trying to create a .csv file using a List<Stuff> type list. In order to use ListToCsvConverter(), I need a List<Dynamic>.
How do I convert a List<Stuff> to a List<Dynamic> so that I can convert it to .csv with ListToCsvConverter()?
"Stuff" model below:
class Stuff {
int id;
String stuffType;
String stuffSize;
String stuffTime;
Stuff({this.id, this.stuffType, this.stuffSize, this.stuffTime});
}
Your problem is that ListToCsvConverter() is not accepting a List<Stuff> but a List<List<dynamic>>.
The first level List is the list of rows for your csv, while the second level List is the list of cells in each row.
I added a getter csvRow in your Stuff class and map to the rows just before calling ListToCsvConverter():
Full source code:
import 'package:faker/faker.dart';
import 'package:csv/csv.dart';
void main() {
String csv = const ListToCsvConverter()
.convert(stuffList.map((stuff) => stuff.csvRow).toList());
print(csv);
}
class Stuff {
int id;
String stuffType;
String stuffSize;
String stuffTime;
Stuff({this.id, this.stuffType, this.stuffSize, this.stuffTime});
List<dynamic> get csvRow => [id, stuffType, stuffSize, stuffTime];
}
final faker = Faker();
final stuffList = List.generate(
100,
(index) => Stuff(
id: faker.randomGenerator.integer(999999, min: 100000),
stuffType: faker.person.name(),
stuffSize: '${faker.randomGenerator.integer(1000)}MB',
stuffTime: faker.date.toString(),
));
Posting a clear answer for people to see.
Initial List is "stuffList".
How do I convert a List<Stuff> to a List<Dynamic> so that I can convert it to .csv with ListToCsvConverter()?
//Create a new dynamic list
List<List<dynamic>> rows = List<List<dynamic>>();
//Convert stuffList to List<List<dynamic>>
for (int i = 0; i < listStuff.length; i++) {
List<dynamic> row = List();
row.add(listStuff[i].id);
row.add(listStuff[i].stuffType);
row.add(listStuff[i].stuffSize);
row.add(listStuff[i].stuffTime);
rows.add(row);
}
//convert the list to csv
final csv = const ListToCsvConverter().convert(rows);
I have a List<MyClass> myClass;, I want to get List<String> myList; from all of myClass.item, is there one line way to convert it?
You can use the map method from List class to loop through the entire list. Don't forget to call toList in the end, as Dart's map returns a kind of Iterable. Please see the code below.
class Employee {
int id;
String firstName;
String lastName;
Employee(
this.id,
this.firstName,
this.lastName,
);
}
void main() {
List<Employee> employees = <Employee>[
Employee(1, "Adam", "Black"),
Employee(2, "Adrian", "Abraham"),
Employee(3, "Alan", "Allan"),
];
List<String> myList = employees.map((item)=>item.firstName).toList();
print(myList);
}
I have simple class structure that has an array part of its fields. I want to store this class in a list. The problem is when adding additional class structures to the list it handles it as if it's a direct update and not referenced.
public class TrayLayout
{
public int[] inerD { get; set; }
public class TrayLayout
{
public int[] inerD { get; set; }
public TrayLayout(int[] inerD)
{
this.inerD = inerD;
}
}
public partial class Form1 : Form
{
public List<TrayLayout> trayL = new List<TrayLayout>();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int[] aa = new int[2];
aa[0]=1;
aa[1]=2;
//add the new class to TrayLoayout
trayL.Add(new TrayLayout(aa));
aa[0]=3;
aa[1]=4;
//add the new class to TrayLoayout using input array
trayL.Add(new TrayLayout(aa));
aa[0]=5;
aa[1]=6;
//add the new class to TrayLoayout
trayL.Add(new TrayLayout(aa));
textBox1.Text = "the numbers accepted \n"+ trayL[0].inerD[0].ToString() + " , " +trayL[0].inerD[1].ToString() + " \n" + trayL[1].inerD[0].ToString() + " , " +trayL[1].inerD[1].ToString() + " \n" + trayL[2].inerD[0].ToString() + " , " +trayL[2].inerD[1].ToString() ;
}
I get in TextBoxes it shows the last input 5,6 5,6 5,6 instead of 1,2 3,4 5,6. I must be missing something?
You always refer to the same int array, overwriting the previous values.
You have created 1 ArrayObject aa. And you are overwriting the first 2 values, when you assign 3 and 4. And when you assign 5 and 6 you have overwritten 3 and 4.
Create 3 different arrays or make aa[0] to aa[5].
Assigning the int array to the TrayLayout class does not make a copy. Each instance of the TrayLayout class in your example has a reference to the same array, so when you update it following the call to the TrayLayout constructor, all your instances of TrayLayout see the same values.
Either copy the array internally in the TrayLayout constructor, or (as others are suggesting) use different arrays in the constructor calls.
You need to replace this:
int[] aa = new int[2];
aa[0]=1;
aa[1]=2;
//add the new class to TrayLoayout
trayL.Add(new TrayLayout(aa));
aa[0]=3;
aa[1]=4;
//add the new class to TrayLoayout
trayL.Add(new TrayLayout(aa));
aa[0]=5;
aa[1]=6;
//add the new class to TrayLoayout
trayL.Add(new TrayLayout(aa));
With this:
trayL.Add(new TrayLayout(new int[]{1,2}));
trayL.Add(new TrayLayout(new int[]{3,4}));
trayL.Add(new TrayLayout(new int[]{5,6}));
Edit
You could do it like this:
var start=1;
var end=13;
trayL.Add(new TrayLayout(Enumerable.Range(start,end).ToArray()));
Problem: I can't access the count of items in a SelectList
I have an HtmlHelper method that returns a SelectList:
public static SelectList FilterSelectList(this HtmlHelper helper, List<Stuff> eList, string dept)
{
List<Stuff> returnList = new List<Stuff>();
//Do Stuff
return new SelectList(returnList, "ID", "Name");
}
I then have a test which confirms that the filter was done correctly:
// Arrange
List<Stuff> eList = MVCMocks.GetList();
string dept = "T";
int expectedCount = eList.FindAll(e => e.Dept == dept).Count;
// Act
var actual = HtmlHelpers.FilterSelectList(helper, eList, dept);
// Assert
Assert.AreEqual(expectedCount, actual.Count, "The list was not properly filtered.");
Calling actual.Count results in an error.
I'm hoping this is just a case of me having a stupid oversight, but I've been banging my head on this for a while. Prove me right! :)
EDIT: Stuff I've Tried
actual.Count
actual.Count()
actual.Items.Count()
actual.GetEnumerator().?
You need actual.Count() (note parens!) not actual.Count.