How to store array values depending on a condition? - arrays

I have variables of type string, [int], bool
var books:[String] = ["Hobbit","LOTR","Fellowship"]
var chaptersToRead:[[Int]] = [[1],[1,3],[2,3]]
var read:[Bool] = [false,true,true]
I have function display() so that I can see details about all the books individually
func display() -> [[Any]] {
var output = [[Any]]()
for i in 0..<books.count {
output.append([books[i], chaptersToRead[i], read[i]])
}
return output
}
I like to store values of books in two arrays based on condition if chaptersToRead = 1, as follows
var booksAssigned:[String] = ["Hobbit","LOTR"]
var readStatus:[Bool] = [false,true]
I tried to get the above result by doing the following below which is not working. What am I doing wrong?
var booksAssigned:[String] = []
var readStatus:[Bool] = []
for (index, books) in display().enumerated()
{
if chaptersToRead.joined().contains(1)
{
//I am getting signal SIGABRT error here
booksAssigned = books as! [String]
}
}
for (index, status) in display().enumerated()
{
if chaptersToRead.joined().contains(1)
{
//I am getting signal SIGABRT error here
readStatus = status as! [Bool]
}
}

Try this:
var booksAssigned:[String] = []
var readStatus:[Bool] = []
for (index, chapters) in chaptersToRead.enumerated() {
if chapters.contains(1) {
booksAssigned.append(books[index])
readStatus.append(read[index])
}
}
print(booksAssigned)
print(readStatus)
Edit: Edited as per #Nirav D's suggestion.

Remove var keyword from if blocks. You have already declared those variables.
var booksAssigned:[Any] = []
var readStatus:[Any] = []
for (index, books) in display().enumerated()
{
if chaptersToRead.joined().contains(1)
{
booksAssigned = books
}
}
for (index, status) in display().enumerated()
{
if chaptersToRead.joined().contains(1)
{
readStatus = status
}
}
This works.

Related

How can I merge 2 dictionaries into one array?

My JSON data look like this image below. Now I wanna merge the value of Shop Type and Promotion into one to use as collection view data. How can I do that?
I just filter the response data from the server like this:
var dataBanDau: [SDFilterModel] = []
var quickData: [SDFilterModel] = []
let filters: [SDFilterModel] = data
self.filterEntries = filters
//let nsarray = NSArray(array: self.filterEntries! , copyItems: true)
// self.filterEntriesStoreConstant = nsarray as! Array
self.dataBanDau = filters
for i in 0..<self.dataBanDau.count {
if self.dataBanDau[i].search_key.count == 0 {
self.quickData.append(self.dataBanDau[i])
}
}
self.quickData = self.quickData.filter {
$0.type != "range"
}
DispatchQueue.main.async {
//Note: Reload TableView
self.quickFilterCollection.reloadData()
completed(true)
}
}
the class SDFilterModel:
class SDFilterModel: DSBaseModel {
var name = String()
var type = String()
var is_expanded = Int()
var search_key = String()
var filterEntries : [SDFilterModel]?
override func copy(with zone: NSZone? = nil) -> Any {
// This is the reason why `init(_ model: GameModel)`
// must be required, because `GameModel` is not `final`.
let copy = SDFilterModel(dict: self.dictionary)
if let arrAttribute = NSArray(array: self.value , copyItems: true) as? [AttributeValueModel] {
copy.value = arrAttribute
}
return copy
}
override init(dict: Dictionary<String, Any>) {
super.init(dict: dict);
value = self.valueParse()
name = dict.getString(forKey: "name")
type = dict.getString(forKey: "type")
search_key = dict.getString(forKey: "search_key")
is_expanded = dict.getInt(forKey: "is_expanded")!
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
var value: [AttributeValueModel] = [];
func valueParse()-> [AttributeValueModel] {
guard let childs = (self.dictionary["value"]) as? [Dictionary<String, AnyObject>]
else { return [] }
var output: [AttributeValueModel] = [];
for aDict in childs {
let item = AttributeValueModel(dict:aDict);
// if type == .Range && item.option_id == "0" {
// item.setRangeOptionID(aValue: item.option_name!)
// }
//
output.append(item);
}
return output;
}
Let be Assume you have let myArray = [1,2,3,4,5,6,7,8]
Now you wanted to square of each and every element in the array,
With for loop you do like this
for item in myArray {
print(item * item)
}
Now assume item = $0
With for map you jus do
myArray.map({ $0 * $0 })
Both will gave same output.
map : Use to do same operation on every element of array.
flatmap : It is used to flattern the array of array.
let myArr = [[1,2,3],[4,5,6,7]]
and you want o/p as [1,2,3,4,5,6,7]
So can get above output with myArr.flatMap({$0})
Now back to your question.
let reqArray = myModel.data.map({ $0.value }).flatMap({ $0 })
First, map gaves you array-of-array of key value but you need a single array, so for that you need to use flatmap.
You can take ref : https://medium.com/#Dougly/higher-order-functions-in-swift-sorted-map-filter-reduce-dff60b5b6adf
Create the models like this
struct Option {
let name: String
let searchKey: String
let id: String
}
struct Model {
let type: String
let name: String
let isExpanded: Bool
let value: [Option]
}
You should get the options array values and join all the arrays
let models:[Model] = //...
let collectionViewArray = models.map { $0.value }.reduce([Option](), +)
Using for loop
var collectionViewArray = [Option]()
for model in models {
collectionViewArray.append(contentsOf: model.value)
}

How to select items from array no repeat

I'm building swift quiz app I want to show random questions with no repeat.
var sorular: Array = ["soru1","soru2","soru3","soru4","soru5"]
var gorulensoru = [Int]()
var sayac: Int = 0
var sorularcevaplar = ["D","Y","D","Y","D"]
var cevaplar: Array<Any> = []
var dogru: Int = 0
var yanlis: Int = 0
func chooseRandom() -> String {
if gorulensoru.count == sorular.count { return "" }
let randomItem = Int(arc4random() % UInt32(sorular.count)) //get
if (gorulensoru.contains(randomItem)) {
return chooseRandom()
}
let requiredItem = sorular[randomItem]
gorulensoru.append(randomItem)
return requiredItem
}
override func viewDidLoad() {
super.viewDidLoad()
soruText.text = chooseRandom()
}
What is the problem in my code? I'm tried insert selected random item to inside gorulensoru array but it shows again selected item
if (gorulensoru.contains(randomItem)) {
return chooseRandom()
}
This statement doesn't run.
Your code only runs once.
Also, you shouldn't include potential infinite recursive calls because it can easily get to a level where it causes a hang or crash.
Use shuffle() and then iterate over the array.
Change this and it may work:
let requiredItem = sorular[randomItem]
gorulensoru.append(requiredItem)

Issue with storing data within an Array - Swift

I currently have my set-up as followed:
I am running a query in Firebase to extract all of the genres within an array of genres, like so:
var genresLabelIndex : [String] = ["Horror", "Fiction", "Romance"]
Then I am creating a blank arrays for each of the genres to be able to store the information of the genres within each of the areas like so:
var horrorData = [InformationForFeed]()
var fictionData = [InformationForFeed]()
var romanceData = [InformationForFeed]()
InformationForFeed looks like so:
class InformationForFeed {
fileprivate var _uploadKey:String!
fileprivate var _userKey:String!
fileprivate var _imageURL:String!
fileprivate var _socialMedia:[String]
var uploadKey:String!{
return _uploadKey
}
var userKey:String!{
return _userKey
}
var imageURL:String!{
return _imageURL
}
init(dictionary:Dictionary<String,AnyObject>, socials: [String]) {
_socialMedia = socials
if let uploadKey = dictionary["upload_key"] as? String {
self._uploadKey = uploadKey
}
if let userKey = dictionary["user_key"] as? String {
self._userKey = userKey
}
if let imageURL = dictionary["imageUrl"] as? String {
self._imageURL = imageURL
}
}
}
I am then creating an Array of the list of genres arrays like so:
1) First I am creating an empty array of arrays like this:
var genreArrayIndex : [[InformationForFeed]] = []
2) Then within my init() of the UIView I am setting what will be in the array like this:
genreArrayIndex = [self.horrorData, self.fictionData, self.romanceData]
I then will run a function called getData() that will run my query and start storing the information.
I store my information of each genre in a tempArray, and then I set the genreArrayIndex[index] to equal the tempArray and then clear the tempArray as seen in getData below.
func getData() {
for genre in genresLabelIndex {
let dbReference = Database.database().reference().child("genres").child(genre)
let query = dbReference.queryLimited(toLast: 6)
query.observeSingleEvent(of: .value, with: { (snapshot : DataSnapshot) in
if snapshot.childrenCount > 0 {
for s in snapshot.children.allObjects as! [DataSnapshot] {
let item = s.value as! Dictionary<String,AnyObject?>
let facebook = (s.childSnapshot(forPath: "social_links").value as? NSDictionary)?["facebook_link"]
let audible = (s.childSnapshot(forPath: "social_links").value as? NSDictionary)?["audible_link"]
let amazon = (s.childSnapshot(forPath: "social_links").value as? NSDictionary)?["amazon_link"]
var socialsArray = [String]()
if facebook != nil {
socialsArray.append(facebook! as! String)
} else {
socialsArray.append("nil")
}
if audible != nil {
socialsArray.append(audible! as! String)
} else {
socialsArray.append("nil")
}
if amazon != nil {
socialsArray.append(amazon! as! String)
} else {
socialsArray.append("nil")
}
let data = InformationForFeed(dictionary: item as Dictionary<String,AnyObject>, socials: socialsArray)
self.newArray.append(data)
}
}
self.genreArrayIndex[self.genreArrayIndexCount] = self.newArray
self.genreArrayIndexCount = self.genreArrayIndexCount + 1
self.newArray.removeAll()
self.internalIndex = self.internalIndex + 1
if self.internalIndex == self.genresLabelIndex.count {
self.tableView.reloadData()
}
})
}
}
My tempArray looks like this:
var newArray = [InformationForFeed]()
The index looks like this:
var genreArrayIndexCount : Int = 0
Now comes the issue....
All of the information is properly being stored in the genreArrayIndex .....but... it is not actually storing the information in the arrays that being stored in genreArrayIndex.
So in other words if you were to print(self.genreArrayIndex) it would be fully populated. But if you were to print(self.fictionData) it would be blank.
How can I resolve this?
Array is a value type. That means its contents are copies. Initializing genreArrayIndex with empty horrorData, (and others) and then filling it with getData() does not also copy the data back into horrorData. I would recommend eliminating
genreArrayIndex = [self.horrorData, self.fictionData, self.romanceData]
and replacing horrorData, fictionData, ... with computed properties. Perhaps like this.
var horrorData: [InformationFeed] {
return genreArrayIndex[0]
}

Extracting JSON Data -

I have the following JSON data structure being pulled from FBSDKGraphRequest.
data = (
{
id = "<USER_ID_GOES_HERE>";
name = "Tom Jones";
picture = {
data = {
"is_silhouette" = 0;
url = "<USER_IMAGE_URL_GOES_HERE>";
};
};
},
{
id = "<USER_ID_GOES_HERE>";
name = "Tom Jones";
picture = {
data = {
"is_silhouette" = 0;
url = "<USER_IMAGE_URL_GOES_HERE>";
};
};
},
{
id = "<USER_ID_GOES_HERE>";
name = "Tom Jones";
picture = {
data = {
"is_silhouette" = 0;
url = "<USER_IMAGE_URL_GOES_HERE>";
};
};
},
I want to extract the data and place it into an array. I am having difficulty with the first "data" key.
Heres my FBSDKGR:
let params = ["fields": "name, picture.type(large)"]
let request = FBSDKGraphRequest(graphPath: "me/taggable_friends", parameters: params)
request!.start { (connection, result, error) -> Void in
if error != nil {
print("There is some error getting friends", error!)
}
else if result != nil {
print("Here is the result", result!)
With an extra dependency, if you don't mind.
import SwiftyJSON
let json = JSON(result) // after you get result from FBSDKGR
let data = json["data"].array
for (index, _) in data.enumerated() {
if let id = json["data", index, "id"].int {
// add to your array
if let name = json["data", index, "name"].string {
// continue nesting...
}
}
}
As your JSOND dta is array of dictionary so , we can cast the result by the following way . First of all we will take two array , one is for names list and other is for picture details . here picture details array is array of dictionary . let's go for code
var namesArray = [String]()
var ImageDetailsArrayDict= [[String :AnyObject]]()
let params = ["fields": "name, picture.type(large)"]
let request = FBSDKGraphRequest(graphPath: "me/taggable_friends", parameters: params)
request!.start { (connection, result, error) -> Void in
if error != nil {
print("There is some error getting friends", error!)
}
else if result != nil {
print("Here is the result", result!)
if let response = result["data"] as? [[String :AnyObject]] {
for i in 0..<response.count {
namesArray.append(response[i]["name"] as! String)
ImageDetailsArrayDict.append(response[i]["picture"])
}
}
}
}
Now , we have two array . so we can easily populate it in the tableView .
Good luck .

How to remove a swift 2 array element is not at index

How to remove a swift 2 array element is not at index?
protocol Food { //Еда
var name: String {get}
func taste() -> String
var pr: Int {get}
}
protocol Storable: Food {
var expired: Bool {get}
var daysToExpire: Int {get}
}
class Apple: Food { //Яблоко
var name = "Яблоко"
func taste() -> String {
return "Сладкое"
}
var pr = 0
}
class Grapes: Storable { //виноград
var name = "Виноград"
func taste() -> String {
return "Кислый"
}
var pr = 0
var expired = false
var daysToExpire = 5
}
class Banana: Storable { //Банан
var name = "Банан"
func taste() -> String {
return "Сладкий"
}
var pr = 0
var expired = false
var daysToExpire = 9
}
class Potato: Food { //картошка
var name = "Картошк"
func taste() -> String {
return "Сладкая"
}
var pr = 1
}
class Bow: Food { //Лук
var name = "Лук"
func taste() -> String {
return "Горький"
}
var pr = 1
}
class Carrot: Food { //морковь
var name = "Морковь"
func taste() -> String {
return "Сладкая"
}
var pr = 1
}
var apple = Apple()
var grapers = Grapes()
var banana = Banana()
var potato = Potato()
var bow = Bow()
var carrot = Carrot()
var basket: [Food] = [apple, grapers, banana, potato, bow, carrot]
func bite(oneBite: [Food]) {
for bites in basket {
print("Кусаем \(bites.name), ооо на вкус \(bites.taste())")
}
}
bite(basket)
var fridge = [Storable]()//пустой массив типа Storable холодильник
for prod in basket {
if let storableProduct = prod as? Storable where storableProduct.expired == false {
fridge.append(storableProduct)
}
}
var trash = [Storable]() //пустой массив типа Storable мусорка
for i in fridge {
if i.daysToExpire > 6 {
fridge.removeAtIndex(i)
}
}
First of all please post the code rather than screenshots. Nobody who is willing to help is also willing to retype the code for testing.
The index variable i in the loop is a Storable object, not an Int index, that's exactly what the error message says.
Using enumerate you get the index and the object
for (i, storable) in fridge.enumerate {
if storable.days ... {
fridge.removeAtIndex(i)
}
}
But be aware that you certainly will run into the next problem if you are removing items from the object you are enumerating just now.

Resources