If I declare a class property as:
var list = Dictionary<String, StructType[]>()
and then try to add a value from within a class method with:
var structType = StructType()
list[ "A" ] = [ structType ]
I get a runtime EXC_BAD_INSTRUCTION error. However, if I declare the dictionary within the class method and add a value there is no error.
It has something to do with the dictionary having values which are arrays. If I change the declaration to something simpler, like:
var list = Dictionary<String, String>()
then within the class method:
list["A"] = "some string"
works without any issues.
Any ideas?
UPDATE:
I've also tried declaring:
var list = Dictionary<String, String[]>()
and there is no issue referencing the list within a class method.
list[ "A" ] = [ "String1", String2" ]
Also the class declaration:
var list = Dictionary<String, SomeStruct>()
can be referenced within a class method.
UPDATE 2:
The struct is defined as:
struct Firm {
var name = ""
}
If you create your list and class in the following way it should work fine:
struct StructType {
var myInt = 0;
}
class MyClass {
var list = Dictionary<String, StructType[]>()
func myFunc () {
var structType = StructType()
list[ "A" ] = [ structType ]
}
}
var a = MyClass()
a.myFunc()
The following code appears to work for me in a playground.
struct StructType {
}
var list = [String:[StructType]]()
var structType = StructType()
list["A"] = [structType]
Related
struct District {
var district:[String]=["districtName","headQuarters"]
}
var telangana:[district] = ["rangareddy","shamshabad","suryapet","suryapet"]
print(telangana)
I think you're trying to create struct District with districtName and headQuarter as its properties,
struct District {
let districtName: String
let headQuarter: String
}
Now, you can create an array of District like so,
let telangana: [District] = [District(districtName: "rangareddy", headQuarter: "shamshabad"), District(districtName: "suryapet", headQuarter: "suryapet")]
print(telangana)
Your struct name is "District" so it should be:
var telangana:[District] = ["rangareddy","shamshabad","suryapet","suryapet"]
Although this will not compile because an array or Districts cannot be initialised with [String]
You should try something like:
let district1 = District(district:[""rangareddy","shamshabad","suryapet","suryapet""])
var telangana:[District] = [district1]
Create first property in your struct
struct District {
var districtName: String
var headQuarters: String
}
then create array of struct
var telangana: [District] = []
telangana.append(District(districtName: "rangareddy", headQuarters: "shamshabad"))
print(telangana)
I have a Profile Data singleton class as follows.
I am trying to store data into an empty array in a dictionary .
After appending data to the array also the count of the array is 0.
class ProfileData{
static let sharedInstance = ProfileData()
var artistProfileDict = [String : Profile]()
var loggedInUserProfile = Profile(artistName: "John Smith", artistDescription: "Admiral of New England, English soldier, explorer, and author.", totalLikes: "174", totalViews: "200", totalFollowing: "100",totalFollowers:"50",imageUrl:"image_singer", feeds:[] )
private init() {
getProfilesDictionary()
}
func getProfilesDictionary()->[String: Profile]{
artistProfileDict["John Smith"] = loggedInUserProfile
return artistProfileDict
}
func add(array: Feed, artistName: String) {
artistProfileDict[artistName]!.feeds.append(array)
}
}
In another view Controller I am trying to add an array to the empty array in the dictionary as follows
let newFeed = Feed(profilePicture: "image",artistName: "New",
videoUrl: "url",videoTitle:"New", videoViews: "160",likes:
"200",shoutouts: "200",comments: [],votes: "50", dateCreated: Date(),
userActivity :"This user liked your video")
ProfileData.sharedInstance.add(array: newFeed,artistName:"John Smith")
After appending the array to the empty array in the dictionary I still get the count of the array as 0.
I am not able to figure out the problem here. Any help will appreciated . Thank you.
Profile class
struct Profile {
var artistName: String
var artistDescription: String
var totalLikes: String
var totalViews: String
var totalFollowing: String
var totalFollowers: String
var imageUrl: String
var feeds : [Feed]
init(artistName: String,artistDescription:String,totalLikes:String,totalViews:String,totalFollowing:String,totalFollowers:String,imageUrl:String, feeds:[Feed]) {
self.artistName = artistName
self.artistDescription = artistDescription
self.totalLikes = totalLikes
self.totalViews = totalViews
self.totalFollowing = totalFollowing
self.totalFollowers = totalFollowers
self.imageUrl = imageUrl
self.feeds = feeds
}
}
It's working fine
ProfileData.sharedInstance.add(array: newFeed,artistName:"John Smith")
ProfileData.sharedInstance.artistProfileDict["John Smith"]?.feeds.count // 1
Probably you are using wrong class ArtistProfileData instead of ProfileData.
This question already has answers here:
How to group by the elements of an array in Swift
(16 answers)
Closed 6 years ago.
I have an array [modelA,modelB,modelC,modelD,modelE], each element in the array is an instance of a Struct. The Struct has a property "name". for example...
modelA.name = "abc"
modelB.name = "efg"
modelC.name = "hij"
modelD.name = "abc"
modelE.name = "efg"
How can I group elements with the same property value into a new array? i.e. put modelA and modelD into a new array,and put modelB and modelE into another array.
Assume the original array is large.
You can achieve this by using filter(_:):
Returns an array containing, in order, the elements of the sequence
that satisfy the given predicate.
For example, consider that the structure looks like:
struct Model {
var name: String?
}
And you have an array of models:
let allModelsArray = [Model(name: "abc"), Model(name: "efg"), Model(name: "hij"), Model(name: "abc"), Model(name: "efg"), Model(name: "efg"), Model(name: "hij")]
So, you can get your arrays by doing (assuming that you want to filter based on the value of the name):
let abcModelsArray = allModelsArray.filter { $0.name == "abc" }
// [Model(name: Optional("abc")), Model(name: Optional("abc"))]
let hijModelsArray = allModelsArray.filter { $0.name == "hij" }
// [Model(name: Optional("hij")), Model(name: Optional("hij"))]
ALSO:
You mentioned that:
how can I put element which has the same property value into a new
array, such as put modelA and modelD into a new array, and put modelB
and modelE into a new array, if array is large.
Somehow, you might want to use the lazy version of the collection.
Hope this helped.
I have not performance tested this
struct Model {
var type : String
var name : String
}
var modelA = Model(type: "A", name: "abc")
var modelB = Model(type: "B", name: "efg")
var modelC = Model(type: "C", name: "abc")
var modelD = Model(type: "D", name: "efg")
let models = [modelA,modelB,modelC,modelD]
let names = Set(models.map({return $0.name}))
var groupedModels : [String:[Model]] = [:]
for var name in names {
let elements = models.filter({$0.name == name})
groupedModels[name] = elements
}
.reduce solution:
let a = [modelA, modelB, modelC, modelD, modelE]
let arr = a.reduce([:]) { (result, currentModel) -> [String: [Model]] in
var mutableDic = result
if ((mutableDic[currentModel.name]) != nil) {
mutableDic[currentModel.name]?.append(currentModel)
} else {
mutableDic[currentModel.name] = [currentModel]
}
return mutableDic
}
It will return the same dictionary as #Grimxn response. or got from this for loop
var mutableDic = [String : [Model]]()
for aModel in a {
if ((mutableDic[aModel.name]) != nil) {
mutableDic[aModel.name]?.append(aModel)
} else {
mutableDic[aModel.name] = [aModel]
}
}
The key is to use a Dictionary to track for Model that need to be put in the same array, by comparing to it's .name.
I have 2 classes, I have cats object in the AnimalClass and I am parsing jSON and I want to initialize the cats name from the jSON
class AnimalClass: NSObject {
var cats = [catClass]()
.....
}
And
class catClass: NSObject {
var name : String = ""
init(data : NSDictionary)
{
if let add = data["name"] as? String
{
self.name = add
}
Here I am trying to initialize it in the ViewController.swift
var animals = [AnimalClass]()
for(var i = 0; i < data_array.count; i++)
{
if let add = data_array[i] as? NSDictionary
{
self.animals.append(AnimalClass(data: add)) // this works
self.animals.cats.append(AnimalClass(data: add)) // this doesn't work
}
}
My question is for this line self.animals.cats.append(AnimalClass(data: add)) how can append to cats object which is in the AnimalClass.
You are not able to append AnimalClass to cats because cats is an array of catClass objects. You declared it like this:
var cats = [catClass]()
That's why the code below won't work.
self.animals.cats.append(AnimalClass(data: add))
So you should change it to:
self.animals.cats.append(catClass(data: add))
Moreover, class names in Swift should start with capital letter and I recommend you rename catClass to Cat (also dropping the Class suffix)
You will need to make use the init for your cat class.
change the line:
self.animals.cats.append(AnimalClass(data: add))
to:
self.animals.cats.append(CatClass(data: add))
I have an array of type "drugList", and they are derived from a struct "DrugsLibrary":
struct DrugsLibrary {
var drugName = ""
var drugCategory = ""
var drugSubCategory = ""
}
var drugList = [DrugsLibrary]()
//This is the dictionary i'm trying to build:
var dictionary = ["": [""," "]]
My data model is initialized using this function:
func createDrugsList() {
var drug1 = DrugsLibrary()
drug1.drugName = "drug1"
drug1.drugCategory = "Antibiotics"
drug1.drugSubCategory = "Penicillins"
self.drugList.append(drug1)
var drug2 = DrugsLibrary()
drug2.drugName = "drug2"
drug2.drugCategory = "Antibiotics"
drug2.drugSubCategory = "Penicillins"
self.drugList.append(drug2)
var drug3 = DrugsLibrary()
drug3.drugName = "drug2"
drug3.drugCategory = "Antibiotics"
drug3.drugSubCategory = "Macrolides"
self.drugList.append(drug3)
}
my problem is that i'm trying to create a dictionary from the drugList where the key is the drugSubCategory and the value is the drug name. The value should be an array if there are several drugs in this subcategory
for example, the dictionary should look something like this for this example:
dictionary = [
"Penicillins": ["drug1","drug2"]
"Macrolides": ["drug3"]
]
I tried this method:
for item in drugList {
dictionary["\(item.drugSubCategory)"] = ["\(item.drugName)"]
}
this gave a dictionary like this, and it couldn't append drug2 to "Penicllins":
dictionary = [
"Penicillins": ["drug1"]
"Macrolides": ["drug3"]
]
So I tried to append the items into the dictionary using this method but it didn't append anything because there were no common items with the key "" in the data model:
for item in drugList {
names1[item1.drugSubCategory]?.append(item1.drugName)
}
Anyone knows a way to append drug2 to the dictionary?
I would appreciate any help or suggestion in this matter.
You need to create a new array containing the contents of the previous array plus the new item or a new array plus the new item, and assign this to your dictionary:
for item in drugList {
dictionary[item.drugSubCategory] = dictionary[item.drugSubCategory] ?? [] + [item.drugName]
}
You can use .map and .filter and Set to your advantage here. First you want an array of dictionary keys, but no duplicates (so use a set)
let categories = Set(drugList.map{$0.drugSubCategory})
Then you want to iterate over the unique categories and find every drug in that category and extract its name:
for category in categories {
let filteredByCategory = drugList.filter {$0.drugSubCategory == category}
let extractDrugNames = filteredByCategory.map{$0.drugName}
dictionary[category] = extractDrugNames
}
Removing the for loop, if more Swifty-ness is desired, is left as an exercise to the reader ;).
I have two unrelated observations:
1) Not sure if you meant it as an example or not, but you've initialized dictionary with empty strings. You'll have to remove those in the future unless you want an empty strings entry. You're better off initializing an empty dictionary with the correct types:
var dictionary = [String:[String]]()
2) You don't need to use self. to access an instance variable. Your code is simple enough that it's very obvious what the scope of dictionary is (see this great writeup on self from a Programmers's stack exchange post.
Copy this in your Playground, might help you understand the Dictionaries better:
import UIKit
var str = "Hello, playground"
struct DrugsLibrary {
var drugName = ""
var drugCategory = ""
var drugSubCategory = ""
}
var drugList = [DrugsLibrary]()
//This is the dictionary i'm trying to build:
var dictionary = ["":""]
func createDrugsList() {
var drug1 = DrugsLibrary()
drug1.drugName = "drug1"
drug1.drugCategory = "Antibiotics"
drug1.drugSubCategory = "Penicillins"
drugList.append(drug1)
var drug2 = DrugsLibrary()
drug2.drugName = "drug2"
drug2.drugCategory = "Antibiotics"
drug2.drugSubCategory = "Penicillins"
drugList.append(drug2)
var drug3 = DrugsLibrary()
drug3.drugName = "drug2"
drug3.drugCategory = "Antibiotics"
drug3.drugSubCategory = "Macrolides"
drugList.append(drug3)
}
createDrugsList()
print(drugList)
func addItemsToDict() {
for i in drugList {
dictionary["item \(i.drugSubCategory)"] = "\(i.drugName)"
}
}
addItemsToDict()
print(dictionary)