F# - Defining object arrays - arrays

I'm trying to create som sample data for a project I'm doing. For that I need a simple object structure where on objects holds an array of objects. In this case a critict that can hold reviews. The code looks like this:
type Review =
{ MovieName: string;
Rating: double }
type Critic =
{ Name: string;
Ratings: Review[] }
let theReviews = [{ MovieName = "First Movie"; Rating = 5.5 }; { MovieName = "Second Movie"; Rating = 7.5 };]
let theCritic = { Name = "The Critic"; Ratings = [{ MovieName = "First Movie"; Rating = 5.5 }; { MovieName = "Second Movie"; Rating = 7.5 };] }
"the reviews" line is working fine but I can't get the "theCritict" line to work. The error I'm getting is:
Error 1 This expression was expected to have type
Review []
but here has type
'a list
How do I get this to work?

Array literals use [| ... |] rather than [ ... ] which are list literals - you need something like
let theCritic = { Name = "The Critic"; Ratings = [|{ MovieName = "First Movie"; Rating = 5.5 }; { MovieName = "Second Movie"; Rating = 7.5 };|] }
This explains the error - you have used a list literal instead of an array literal

actually you're using array in your Review definition and list in the implementation..and these are really different beasts, list are inmutables (better for concurrency) and support pattern matching while arrays are mutables..I recommend you keep using list except for long collections (really longs)
if you wish keep using list you can do it:
type Review =
{ MovieName: string;
Rating: double }
type Critic =
{ Name: string;
Ratings: Review list }
here you've a more detailed list about differences between list and arrays:
http://en.wikibooks.org/wiki/F_Sharp_Programming/Arrays#Differences_Between_Arrays_and_Lists ...

Related

Newbie: referencing and initializing structure elements within structures

OK, super-newbie Swift learner here with what I am sure is a simple question, that for some reason I cannot wrap my head around.
In the below code, I am creating a (very) simple address book structure just to understand how to reference and initialize the various elements, especially structures within structures. What am I doing wrong and is there a better way to write this? I am getting errors (using Swift Playground).
Errors on the last three lines:
Instance member 'page' cannot be used on the type 'AddressBookStruct'
Instance member 'subscript' cannot be used on type '[AddressPageStruct]'.
Plus, when I set var page = [AddressBookStrcut] I get the error:
Expected member name or constructor call after type name
Thanks in advance for the understanding nudge. :)
struct AddressPageStruct {
let firstName: String
let lastName: String
let cellPhone: Int
init(f: String, l:String, c:Int) {
firstName = f
lastName = l
cellPhone = c
}
}
struct AddressBookStruct {
let color: String
let size: String
var page = [AddressPageStruct]
}
var littleBlackBook = AddressBookStruct.self
littleBlackBook.init(color: "Black", size: "Little")
littleBlackBook.page[0].cellPhone = 6191234567
littleBlackBook.page[0].firstName = "Bob"
littleBlackBook.page[0].lastName = "Smith"
The struct is value type, please check this.
structure vs class in swift language,
you can't make this littleBlackBook.page[0].cellPhone, because cellPhone is constant you use let, instead use the constructor, also I change the page for empty array of AddressPageStruct
import Cocoa
struct AddressPageStruct {
let firstName: String
let lastName: String
let cellPhone: Int
init(f: String, l:String, c:Int) {
firstName = f
lastName = l
cellPhone = c
}
}
struct AddressBookStruct {
let color: String
let size: String
var page = [AddressPageStruct]()
}
var littleBlackBook = AddressBookStruct(color: "Black", size: "Little")
littleBlackBook.page.append(AddressPageStruct(f: "Bob", l: "Smith", c: 6191234567))
print(littleBlackBook.page)
enter code here
var littleBlackBook = AddressBookStruct(color: "Black", size: "Little")
let item = AddressPageStruct(f: "Bob", l: "Smith", c:6191234567 )
littleBlackBook.page.append(item)
littleBlackBook.page.append(AddressPageStruct(f: "Joe", l: "Blog", c: 3123467))
print(littleBlackBook.page[0])
print(littleBlackBook.page[1])
print(littleBlackBook)

Comparing two arrays of objects in Swift

I have two arrays of objects with different sizes.
First one with old data, second one with updated data from server (included old data with new), data can be mixed. I want to get difference between these arrays.
My class
class Station {
var dateOfIssue: Date
var region: String
var locality: String
var bsName: String
var freqIn: String
var freqOut: String
var networkType: String
var provider: String
var bsUsableName: String
...
}
Arrays I want to compare (example)
var a = [Station]()
var b = [Station]()
for _ in 0...5 {
a.append(Station(someRandomStationValue...)
}
b = a
for _ in 0...7{
b.append(Station(someRandomStationValue...) //array "b" will contain all that array "a" contains and some new values
}
How to compare these arrays comparing all fields between and get a new array with differences (like in java: b.removeAll(a))?
You can make use of Set which provides in-built .subtract() and .subtracting() methods which removes the common entries inside both the Sets
struct Station: Hashable,CustomStringConvertible {
var id: Int
var region: String
var locality: String
var bsName: String
// Just to provide a pretty print statement
var description: String {
return "ID: \(id) | region: \(region) | locality: \(locality) | bsName: \(bsName)"
}
}
var stations1 = Set<Station>()
var stations2 = Set<Station>()
for currentNumber in 0...3 {
stations1.insert(Station(id: currentNumber, region: "abc", locality: "abc", bsName: "abc"))
}
for currentNumber in 0...5 {
stations2.insert(Station(id: currentNumber, region: "abc", locality: "abc", bsName: "abc"))
}
// Caluculating the difference here
print(stations2.subtracting(stations1))
As pointed out by #koropok, a good solution is using Set. The first step is to conform your type to Hashable. For classes, you'd have to implement == and hash(into:) functions, but if you use struct you don't have to do anything else other than declaring the conformance. So:
struct Station: Hashable {
var dateOfIssue: Date
var region: String
...
}
Now you should be able to add Station into a Set. Thus:
var a = Set<Station>()
for _ in 0...5 {
a.insert(Station(...))
}
var b = Set<Station>()
a.forEach { b.insert($0) }
for _ in 0...7 {
b.insert(Station(...))
}
let c = b.subtracting(a)
Set also provides a handy initializer that you can use to turn your Station array into a set:
let s = Set(arrayLiteral: [your, station, objects])
As mentioned in comments by koropok you may use subtract method:
// Added to make original code functional
// Station must conform to Hashable protocol in order to be stored in the Set
struct Station: Hashable {
let id: Int
}
var a = [Station]()
for i in 0...5 {
a.append(Station(id:i))
}
var b = [Station]()
for i in 0...7{
//array "b" will contain all that array "a" contains and some new values
b.append(Station(id:i))
}
var c = Set(b)
// c will contain 6 and 7
c.subtract(a)

Class Array Error - ''Type of expression is ambiguous without more context''

I'm pretty new to coding Swift, so please excuse me if this error can be simply fixed!
I created an array, and created a class for each variable. My class looks like this -
class name {
var Name: name?
}
class subject {
var Subject: subject?
}
class grade {
var Grade: grade?
}
And my Array is the following -
var arr = [
[
name: "Koester",
subject: "Science",
grade: "9A"
],
[
name: "Koester",
subject: "Science",
grade: "9B"
]
]
On the Line 8 of the second block of code, "[" I get an error that says -
"Type of expression is ambiguous without more context"
I've tried checking all the other posts related to this "Type of expression is ambiguous without more context" error, but I couldn't find one that was directly related to a variable array, and it seems like I'm the first one that's getting the error inside the array itself.
Thanks!
What I understood from your question is your requirement is you need a class which should have properties which will store the student data and you need to add that data into Array.
Check below code:
Create a calls For StudentDetail like:
class StudentDetail {
//Create Student Properties
var name: String?
var subject: String?
var grade: String?
//Initialise properties this way
init(name: String, subject: String, grade: String) {
self.name = name
self.subject = subject
self.grade = grade
}
}
Now create a class object like:
var user1Detail = StudentDetail(name: "Koester", subject: "Science", grade: "9A")
var user2Detail = StudentDetail(name: "Koester", subject: "Science", grade: "9B")
Now you can store it this way in Array:
var arr = [StudentDetail]()
arr.append(user1Detail)
arr.append(user2Detail)
Now your arr will have student detail and you can access properties of it.
Hope this will help.

Array is nil after appending to it

I have 2 Types, first is Car with property feature and it of the second type Feature.
I have a property cars: [Car], when I append new car to it, it returns nil.
I have created a sample in the snippet below:
class Car {
let make: String
var features: Feature?
let id: String
init(make: String, features: Feature?, id: String) {
self.make = make
self.features = features
self.id = id
}
}
class Feature {
let convertible: String
init(convertible: String) {
self.convertible = convertible
}
}
var cars: [Car]?
var feature: Feature?
let featureElement = Feature(convertible: "yes")
feature = featureElement
let car = Car(make: "SomeMaked", features: feature, id: "ID")
cars?.append(car)
print(cars)
My question is: Shouldn't the array increase its count after appening to it? What am I missing?
Please note that this code is just sample, so ignore typos and coding convention.
You haven't initialized your array.
Replace your var cars: [Car]? with var cars: [Car]? = []

Mapping an array into an object, key is not defined

const lessons = [
[ 'Chemistry', '9AM', 'Mr. Darnick' ],
[ 'Physics', '10:15AM', 'Mrs. Lithun'],
[ 'Math', '11:30AM', 'Mrs. Vitalis' ]
];
let lessonsAsObject = {};
lessons.map(lesson => {
lessonsAsObject[lesson[subject]] = lesson[0];
});
I want to translate this array into an object, matching the data with the keys, subject, time and teacher.
However the code above returns
reference error, "subject is not defined".
You can use array destructuring to get the params from the array, and then create an object for each of them, using the shorthand and computed property names.
If you want the end result to be an object, instead of array of objects, you can combine them to one object using spread syntax, and Object#assign:
You can use the subject as key:
const lessons = [["Chemistry","9AM","Mr. Darnick"],["Physics","10:15AM","Mrs. Lithun"],["Math","11:30AM","Mrs. Vitalis"]];
const lessonsAsObject = Object.assign(...lessons.map(([subject, time, teacher])=> ({
[subject]: {
time,
teacher
}
})));
console.log(lessonsAsObject);
Or the index as key:
const lessons = [["Chemistry","9AM","Mr. Darnick"],["Physics","10:15AM","Mrs. Lithun"],["Math","11:30AM","Mrs. Vitalis"]];
const lessonsAsObject = Object.assign(...lessons.map(([subject, time, teacher], index)=> ({
[index]: {
subject,
time,
teacher
}
})));
console.log(lessonsAsObject);
If you just want an array of objects:
const lessons = [["Chemistry","9AM","Mr. Darnick"],["Physics","10:15AM","Mrs. Lithun"],["Math","11:30AM","Mrs. Vitalis"]];
const lessonsAsObject = lessons.map(([subject, time, teacher])=> ({ subject, time, teacher }));
console.log(lessonsAsObject);
If what you're trying to end up with is an array of objects where the objects have named properties instead of your array positions, then you could do this:
var lessonsList = lessons.map(function(lesson) {
return {subject: lesson[0], time: lesson[1], teacher: lesson[2]};
});
This would give you an array of objects like this:
[{subject: "Chemistry", time: "9AM", teacher: "Mr. Darnick"},
{subject: "Physics", time: "10:15AM", teacher: "Mrs. Lithun"},
{subject: "Math", time: "11:30AM", teacher: "Mrs. Vitalis"}]
If you're looking for some different type of output, then please show an example of exactly what output you're trying to achieve.
However the code above returns the reference error, "subject is not
defined".
That is because the identifier subject is not defined anywhere. If you intended to use it as a static property name, then you can do lesson["subject"]. If you intended to have subject be a variable with some property name in it, then you have to define and assign that variable.

Resources