Let's say I have an array that looks like this:
let games = [
Game(type: "Soccer", value: 1),
Game(type: "Basket", value: 3),
Game(type: "Hockey", value: 5),
Game(type: "Soccer", value: 2),
Game(type: "Soccer", value: 4),
Game(type: "Basket", value: 2)
]
I want a new array with 1 row per type with the values added to each other with matching type. Something like this:
let newGames = [
NewGame(type: "Soccer", value: 7),
NewGame(type: "Basket", value: 5),
NewGame(type: "Hockey", value: 5)
]
Help please. My brain is not cooperating.
struct Game {
let type: String
let value: Int
}
let games: [Game] = [
Game(type: "Soccer", value: 1),
Game(type: "Basket", value: 3),
Game(type: "Hockey", value: 5),
Game(type: "Soccer", value: 2),
Game(type: "Soccer", value: 4),
Game(type: "Basket", value: 2)
]
var totalValueForGame = [String: Int]()
for game in games {
totalValueForGame[game.type] = game.value + (totalValueForGame[game.type] ?? 0)
}
let newGames = totalValueForGame.map { Game(type: $0, value: $1) }
print(newGames)
Output:
[Game(type: "Soccer", value: 7), Game(type: "Hockey", value: 5), Game(type: "Basket", value: 5)]
class Game {
var type: String
var value: Int
init(type: String, value: Int) {
self.type = type
self.value = value
}
}
let games: [Game] = [
Game(type: "Soccer", value: 1),
Game(type: "Basket", value: 3),
Game(type: "Hockey", value: 5),
Game(type: "Soccer", value: 2),
Game(type: "Soccer", value: 4),
Game(type: "Basket", value: 2)
]
var gameTotals:[Game] = []
for key in Set(games.map{$0.type}) {
gameTotals.append(Game(type: key, value: games.filter{$0.type == key}.reduce(0){$0+$1.value}))
}
gameTotals // [{type "Soccer", value 7}, {type "Hockey", value 5}, {type "Basket", value 5}]
My (ugly) solution :D :D
import Cocoa
class Game {
var name:String
var value:Int
init(withName aName:String, andValue value:Int) {
self.name = aName
self.value = value
}
}
var someSports:[Game] = []
var tempDictOfGames:[String:Int] = [:]
var sports:[String] = ["Soccer", "Volleyball", "Tennis", "Rugby", "Tennis", "Soccer", "Tennis", "Cricket"]
var values:[Int] = [1, 5, 3, 8, 2, 9, 4, 7]
for (var i = 0; i < sports.count; i++) {
var availableGameValue:Int? = tempDictOfGames[sports[i]]
if let myValue = availableGameValue {
tempDictOfGames[sports[i]]! += values[i]
} else {
tempDictOfGames[sports[i]] = values[i]
}
}
for (k, v) in tempDictOfGames {
let newGame = Game(withName: k, andValue: v)
someSports.append(newGame)
}
Related
I have the following tow arrays:
fetchedProducts = [
[name: "productName20", id: 20],
[name: "productName3", id: 3],
[name: "productName1", id: 1]
]
sortedProducts = [
[productName1: "1"], // I know the numbers here are string; I need them to be string
[productName20: "20"],
[productName3: "3"]
]
Now I need to sort fetchedProducts based on the order of sortedProducts so it would end up looking like the following:
fetchedProducts = [
[name: "productName1", id: 1],
[name: "productName20", id: 20],
[name: "productName3", id: 3]
]
You can try the following in Swift. Note the dictionaries in Swift are unordered so you have to use arrays for ordered collections:
let fetchedProducts = [
(name: "productName20", id: 20),
(name: "productName3", id: 3),
(name: "productName1", id: 1),
]
let sortedProducts = [
("productName1", "1"),
("productName20", "20"),
("productName3", "3"),
]
let sortedFetchedProducts = sortedProducts
.compactMap { s in
fetchedProducts.first(where: { s.1 == String($0.id) })
}
print(sortedFetchedProducts)
// [(name: "productName1", id: 1), (name: "productName20", id: 20), (name: "productName3", id: 3)]
JavaScipt realisation:
const fetchedProducts = [
{name: "productName20", id: 20},
{name: "productName3", id: 3},
{name: "productName1", id: 1}
];
const sortedProducts = [
{productName1: "1"}, // I know the numbers here are string; I need them to be string
{productName20: "20"},
{productName3: "3"}
];
const sortProducts = (fetchedProducts, sortedProducts) => {
// Extract ordered id from the sortedProducts array
const orderIds = sortedProducts.map(sorted => +Object.values(sorted));
// Find product by sorted id and put into new array
const sortedFetchedProducts = [];
orderIds.forEach(id => {
let product = fetchedProducts.find(item => item.id === id);
sortedFetchedProducts.push(product);
});
return sortedFetchedProducts;
}
const sortedFetchedProducts = sortProducts(fetchedProducts, sortedProducts);
console.log(sortedFetchedProducts);
Output:
[
{ name: 'productName1', id: 1 },
{ name: 'productName20', id: 20 },
{ name: 'productName3', id: 3 }
]
Considering these two objects :
struct Product {
let id: Int
let title: String
let price: Int
let categoryId: Int
}
struct Category {
let id: Int
let name: String
}
And these two object arrays :
let products = [
Product(id: 1, title: "snake", price: 20, categoryId: 1),
Product(id: 2, title: "soap", price: 20, categoryId: 2),
Product(id: 3, title: "cream", price: 20, categoryId: 3),
Product(id: 4, title: "dog", price: 20, categoryId: 1),
Product(id: 5, title: "car", price: 20, categoryId: 4),
]
let categorieItems = [
Category(id: 1, name: "animal"),
Category(id: 2, name: "chemichal"),
Category(id: 3, name: "food"),
Category(id: 4, name: "travel"),
]
How can I handle these two structures to assign in the cellForRowAt indexPath tableView method the product title property to cell.textLabel?.text and the corresponding category name (linked with the categoryId property) contained in categorieItems to the cell.detailTextLabel?.text
For example :
cell.textLabel?.text = snake
cell.detailTextLabel?.text = animal
You can have a function that takes category id and return category from categorieItems
like
private func getCategoryForID(_ categoryId: Int) -> Category {
categorieItems.filter { $0.id == categoryId }
}
Supposing I have these two objects :
struct Product {
let id: Int
let title: String
let price: Int
let categoryId: Int
}
struct Category {
let id: Int
let name: String
}
Then I create two arrays containing those objects :
let products = [Product(id: 1, title: "snake", price: 20, categoryId: 1),
Product(id: 2, title: "soap", price: 20, categoryId: 2),
Product(id: 3, title: "cream", price: 20, categoryId: 3),
Product(id: 4, title: "dog", price: 20, categoryId: 1),
Product(id: 5, title: "car", price: 20, categoryId: 4),
]
let categorieItems = [Category(id: 1, name: "animal"),
Category(id: 2, name: "chemichal"),
Category(id: 3, name: "food"),
Category(id: 4, name: "travel"),
]
I want to create a new array which contains the names of all the product categories :
func handleCategories() -> [String] {
var categoryNames = [String]()
for product in products {
for categorieItem in categorieItems {
if product.categoryId == categorieItem.id {
categoryNames.append(category.name)
}
}
}
return categoryNames
}
This method works but I want to write one with closure (I guess map() should works)
The result should be :
categoryNames = ["animal", "chemichal", "food", "animal", "travel"]
Make a dictionary that keys the category by id, and map each product into a category by looking up its categoryId in that dict.
I used a force unwrap, assuming that products don't contain any invalid categoryIds.
struct Product {
let id: Int
let title: String
let price: Int
let categoryId: Int
}
struct Category {
let id: Int
let name: String
}
let products = [
Product(id: 1, title: "snake", price: 20, categoryId: 1),
Product(id: 2, title: "soap", price: 20, categoryId: 2),
Product(id: 3, title: "cream", price: 20, categoryId: 3),
Product(id: 4, title: "dog", price: 20, categoryId: 1),
Product(id: 5, title: "car", price: 20, categoryId: 4),
]
let categorieItems = [
Category(id: 1, name: "animal"),
Category(id: 2, name: "chemichal"),
Category(id: 3, name: "food"),
Category(id: 4, name: "travel"),
]
let categoriesById = Dictionary(uniqueKeysWithValues:
categorieItems.map { (key: $0.id, value: $0) }
)
let productCategoryNames = products.map { categoriesById[$0.categoryId]!.name }
print(productCategories)
I need to make a function that returns all parent nodes from a specific node in a tree structure.
This is an example of the structure:
struct Node
{
var name: String
var id: Int
var parentId: Int?
var children: [Node]
init(name: String, id: Int, children: [Node], parentId: Int?)
{
self.name = name
self.id = id
self.children = children
self.parentId = parentId
}
}
This would be an array of Node.
Array(
Node("A1", 1, [
Node ("A11", 11, [
Node("A111", 111, []),
Node("A112", 112, [])
]
)]),
Node("A2", 2, [
Node ("A21", 21, [
Node("A211", 211, []),
Node("A212", 212, [])
]
)]),
)
)
If I select Note "112" I should get an array like this:
[Node("A1", 1, [...]), Node ("A11", 11, [...]]
Any ideas how I can do this?
Here's a testable example:
let nodeA111 = Node(name: "A111", id: 111, children: [], parentId: 11)
let nodeA112 = Node(name: "A112", id: 112, children: [], parentId: 11)
let nodeA211 = Node(name: "A211", id: 211, children: [], parentId: 21)
let nodeA212 = Node(name: "A212", id: 212, children: [], parentId: 21)
let nodeA11 = Node(name: "A11", id: 11, children: [nodeA111, nodeA112], parentId: 1)
let nodeA21 = Node(name: "A21", id: 21, children: [nodeA211, nodeA212], parentId: 2)
let nodeA1 = Node(name: "A1", id: 1, children: [nodeA11], parentId: nil)
let nodeA2 = Node(name: "A2", id: 2, children: [nodeA21], parentId: nil)
let nodes: [Node] = [nodeA1, nodeA2]
// This is the function I want to do
func getParentNodes(forNode node: Node) -> [Node]
{
return []
}
I appreciate the help.
Is it possible to map an array with a function that takes in two arguments?
Something like this:
let arr = [2,5,1,4,8,4]
let bankRateArr = arr.map(BankRate.init(amount:interestRate:))
class BankRate {
let amount: Int
let interestRate: Float
init(amount: Int, interestRate: Float) {
self.amount = amount
self.interestRate = interestRate
}
}
If you want to pass the same interest rate to all values, you can do:
class BankRate: CustomStringConvertible {
let amount: Int
let interestRate: Float
init(amount: Int, interestRate: Float){
self.amount = amount
self.interestRate = interestRate
}
var description: String {
return "amount: \(amount), rate: \(interestRate)"
}
}
let arr = [2, 5, 1, 4, 8, 4]
let bankRateArr = arr.map { BankRate(amount: $0, interestRate: 0.04) }
print(bankRateArr)
Output:
[amount: 2, rate: 0.04, amount: 5, rate: 0.04, amount: 1, rate: 0.04, amount: 4, rate: 0.04, amount: 8, rate: 0.04, amount: 4, rate: 0.04]
If you want each to have their own, you can do it with tuples:
let arr2 = [(2, 0.04), (5, 0.07), (1, 0.1), (4, 0.035), (8, 0.25), (4, 0.2)]
let bankRateArr2 = arr2.map { BankRate(amount: $0.0, interestRate: Float($0.1)) }
print(bankRateArr2)
Output:
[amount: 2, rate: 0.04, amount: 5, rate: 0.07, amount: 1, rate: 0.1, amount: 4, rate: 0.035, amount: 8, rate: 0.25, amount: 4, rate: 0.2]
And thanks to Martin R, the 2nd example can be shorted a bit as:
let arr3: [(Int, Float)] = [(2, 0.04), (5, 0.07), (1, 0.1), (4, 0.035), (8, 0.25), (4, 0.2)]
let bankRateArr3 = arr3.map(BankRate.init)
print(bankRateArr3)
Assuming that you will have two separate arrays
let amounts = [2, 5, 1, 4 ,8 ,4]
let rates: [Float] = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]
you could use
let bankRates = zip(amounts, rates).map(BankRate.init)