Convert List<String> to List<dynamic> - arrays

I have created a list in my program as a String list as below.
List<String> finalcats = [];
Then I added used shred preferences since I want to use it in another page
prefs.setStringList("postcategories", finalcats);
Now I want to retrieve this in another page.
prefs.getStringList("postcategories") works fine for retrieving but I want it as a List .
How can I convert the List finalcats = []; to List = [];

The getStringList method always return List<String>. You can cast this using as keyword. For example
List<String> categories = prefs.getStringList("postcategories");
List<dynamic> dynamicCategories = categories as List<dynamic>;
Or you can loop over the list and convert each element into a Map like this
categories.map((value) => {'key': value}).toList();

Related

How to get from database list instead of list of lists?

I have columns with regions. I need get all unique values to List.
The follow function return List of Lists:
getListOfRegionsFromDB() async {
String sql_get_regions = """SELECT DISTINCT(region) FROM "public"."ftp_files"; """;
List<dynamic> result = await connection.query(sql_get_regions);
print(result);
}
And I am getting result like:
[[Tverskaja_obl], [Belgorodskaja_obl], [Uljanovskaja_obl], [Jaroslavskaja_obl]]
But I want to:
["Tverskaja_obl", "Belgorodskaja_obl", "Uljanovskaja_obl", "Jaroslavskaja_obl"]
Is there any short way to do it? I see only one way -- to iterate throw data with for loop.
I am using PostgreSQL.

Find objects that include an array that contains all elements of a second array

I'm trying to filter a set of objects based on values in one of their elements based on another array. I've got it working with filter just fine if the search is "OR" - it returns give me all objects for which at least one of the strings in the search array is found.
But I can't figure out how to make it work as an AND search - returning only the objects that match ALL of the strings in the search array.
Example:
struct Schedule {
let title: String
let classTypes: [String]
}
let schedule1 = Schedule(title: "One", classTypes: ["math","english","chemistry","drama"])
let schedule2 = Schedule(title: "Two", classTypes: ["pe","math","biology"])
let schedule3 = Schedule(title: "Three", classTypes: ["english","history","math","art"])
let schedules = [schedule1, schedule2, schedule3]
let searchArray = ["math", "english"]
//works for OR - "math" or "english"
var filteredSchedules = schedules.filter { $0.classTypes.contains(where: { searchArray.contains($0) }) }
I'd like to find a way for it to use the same search array
let searchArray = ["math", "english"]
But only return items 1 & 3 - as they both have BOTH math and english in the list.
There are good examples of AND conditions when the AND is across different search criteria: car type and colour - but I've been unable to find an example where the criteria are dynamically based on items in an array. For context, I could have dozens of schedules with 20+ class types.
You can work with a Set, isSubset will return true if the schedules element contains all elements of the searchSet
let searchSet = Set(searchArray)
var filteredSchedules = schedules.filter { searchSet.isSubset(of: $0.classTypes) }
As suggested by #LeoDabus it might be worth changing the type of classTypes to Set instead of arrays (if order doesn't matter) since they seems to be unique and then the filtering can be done in the opposite way without the need to convert searchArray each time
var filteredSchedules = schedules.filter { $0.classTypes.isSuperset(of: searchArray) }

Put all maps inside one list

My problem with Flutter is when I'm converting an array to a list, there is every item is a separated list and I want all the items in just one list.
Example output when putting 2 items:
[{title: ITEM1}, {title: ITEM2}]
I want to put like this:
[{title: ITEM1, title: ITEM2}]
I hope you guys understand the problem
void _addPecas() {
if ((_pecasController.text.isEmpty) ||
((_pecasController.text.trimLeft() == ("")))) {
print("Campo Vazio");
} else {
setState(() {
Map<String, dynamic> newPeca = Map();
newPeca["title"] = _pecasController.text.trimLeft();
_pecasController.text = "";
_pecasList.add(newPeca);
print(_pecasList);
});
}
}
if [{title: ITEM1, title: ITEM2}] is what you want to achieve,
The problem here is that you are creating a new Map called newPeca every time your function runs. .
Map<String, dynamic> newPeca = Map();
So by the time you set your values you call _pecasList.add(newPeca); that new map will be appended to your List thus you get [{title: ITEM1}, {title: ITEM2}]
Working with the assumption that you want only one Map in _pecaList, _newPeca should always reference that one Map
Map<String, dynamic> newPeca = _pecaList[0]
then you can add your desired values newPeca["title"] = _pecasController.text.trimLeft();
One more problem you'll run into, you want to have duplicate keys in the Map, which is not possible.
The newer value in the map will overwrite the existing one.
E.g
newPeca[title] = "Item 1"
newPeca[title] = "Item 2"
newPeca[title] will end up being Item 2
As I understood, you are asking for one Map inside List and add values into that Map and finally add it into a List. Here is how you can do it:
Map<String, dynamic> newPeca = Map();
if (_pecasController.text.isEmpty ||
_pecasController.text.trimLeft() == ("")) { // you had too much unwanted brackets here
print("Campo Vazio");
} else {
setState(() {
newPeca["title"] = _pecasController.text.trimLeft(); // you have to have unique key if you want to keep in one Map. See the dart pad example I have provided a link below
_pecasController.text = "";
// _pecasList = [newPeca]; // this is also working without outside .add() but if the list is long, im not recommending this.
print(_pecasList);
});
}
// outside the iteration
_pecasList.add(newPeca);
Edit simple dart example in dartpad
Update:
Make sure this: Map<String, dynamic> newPeca = Map(); outside the iteration. This way you are not creating Map for each and every iteration. You are adding to same map and that map you should add after each iteration to the List or just create empty list assign as a new list in each and every iteration(Btw, not the performant way).
Secondly, when you add to the list inside iteration each and every time map will add to the list.
Finally, Even if you make those right, your map will not take same value as title because the reason is your key of the map entry is title and you cannot have duplicate keys inside map and the list should be outside the iteration.

Find the element in custom array and append the value in one of its property(which is also an array) of custom array in swift

#objc class CplModel:NSObject {
var cplModel:UserCplModel = UserCplModel(json: [:])
var courseData:[CourseModel] = [CourseModel]()
var feedData:[FeedsModel] = [FeedsModel]()
var assessmentData:[AssessmentModel] = [AssessmentModel]()
var userCourseData:[UserCourseModel] = [UserCourseModel]()
init(jsonUserCPlModel:[String:Any]){
if let value = jsonUserCPlModel[""] as? [String:Any]{
self.cplModel = UserCplModel(json: value)
}
}
init(jsonAssessmentAndCourseData:[String]) {
}
}
I am making three Firebase calls and all three are interlinked and want to populate data in above model.
Here comes the issue:
For 1st API call I need to populate only cplModel:UserCplModel property
For 2nd ApI call I need to populate courseData:[CourseModel] and assessmentData:[AssessmentModel]
But the index should remain the same for every populating data.
I mean to say is for 1st index of cplModel, I need to insert the courseData or assessmentData but the response of 2nd API comes later and I need to insert the data in particular index only.

swift - using .map on struct array

i have a struct array that i want "break up" into smaller arrays that can be called as needed or at least figure out how i can map the items needed off one text value.
the struct:
struct CollectionStruct {
var name : String
var description : String
var title : String
var image : PFFile
var id: String
}
and the array made from the struct
var collectionArray = [CollectionStruct]()
var i = 0
for item in collectionArray {
print(collectionArray[i].name)
i += 1
}
printing partArray[i].name gives the following result:
pk00_pt01
pk00_pt02
pk00_pt03
pk01_pt01
pk01_pt02
pk01_pt03
pk01_pt04
pk01_pt05
pk01_pt06
pk01_pt07
pk01_pt08
this is just some test values but there could be thousands of entries here so i wanted to filter the entire array just by the first 4 characters of [i].name i can achieve this by looping through as above but is this achievable using something like .map?
I wanted to filter the entire array just by the first 4 characters of
[i].name
You can achieve this by filtering the array based on the substring value of the name, as follows:
let filteredArray = collectionArray.filter {
$0.name.substring(to: $0.name.index($0.name.startIndex, offsetBy: 4)).lowercased() == "pk00"
// or instead of "pk00", add the first 4 characters you want to compare
}
filteredArray will be filled based on what is the compared string.
Hope this helped.
If you want to group all data automatically by their name prefix. You could use a reducer to generate a dictionary of grouped items. Something like this:
let groupedData = array.reduce([String: [String]]()) { (dictionary, myStruct) in
let grouper = myStruct.name.substring(to: myStruct.name.index(myStruct.name.startIndex, offsetBy: 4))
var newDictionart = dictionary
if let collectionStructs = newDictionart[grouper] {
newDictionart[grouper] = collectionStructs + [myStruct.name]
} else {
newDictionart[grouper] = [myStruct.name]
}
return newDictionart
}
This will produce a dictionary like this:
[
"pk00": ["pk00_pt01", "pk00_pt02", "pk00_pt03"],
"pk01": ["pk01_pt01", "pk01_pt02", "pk01_pt03", "pk01_pt04", "pk01_pt05", "pk01_pt06", "pk01_pt07"],
"pk02": ["pk02_pt08"]
]
Not sure if i am understanding you correctly but it sounds like you are looking for this...
To create a new array named partArray from an already existing array named collectionArray (that is of type CollectionStruct) you would do...
var partArray = collectionArray.map{$0.name}

Resources