How can I optimize the code below for searching an array of maps for a specific key-value (and then return the other key-values)?
type userMap struct {
JiraUsername string
CHProjectID int
CHID string
}
func main() {
var userMaps []userMap
userMaps = append(userMaps, userMap{
JiraUsername: "ted",
CHProjectID: 81,
CHID: "23jk3f32jl3323",
})
fmt.Println(GetUserInfo(userMaps, "ted"))
}
func GetUserInfo(userMaps []userMap, jiraUsername string) (CHProjectID int, CHID string) {
for _, u := range userMaps {
if u.JiraUsername == jiraUsername {
return u.CHProjectID, u.CHID
}
}
return 0, ""
}
Your code is reasonable, but it's not array of map, it's slice of struct. The efficient way would be
type userMap struct {
JiraUsername string
CHProjectID int
CHID string
}
type UsersMap map[string]userMap
func main() {
userMaps := make(UsersMap)
userMaps["ted"] = userMap{
JiraUsername: "ted",
CHProjectID: 81,
CHID: "23jk3f32jl3323",
}
fmt.Println(GetUserInfo(userMaps, "ted"))
}
func GetUserInfo(userMaps UsersMap, jiraUsername string) (CHProjectID int, CHID string) {
if u, ok := userMaps[jiraUsername]; ok {
return u.CHProjectID, u.CHID
}
return 0, ""
}
This doesn't require loop and has O(1) complexity.
Related
In this code snippet
protocol MyProtocol {}
extension Int: MyProtocol {}
let a: Array<MyProtocol> = Array<Int>()
let b: ArraySlice<MyProtocol> = a[...]
let c: Array<Int> = a as! Array<Int>
let d: ArraySlice<Int> = b as! ArraySlice<Int>
d warns with Cast from 'ArraySlice<MyProtocol>' to unrelated type 'ArraySlice<Int>' always fails.
Why can't a Slice be cast in the same way as the original Array? Can this snippet be modified to give the Array casting behaviour to the Slice?
This is basically due to how generic variance in Swift works.
Only few types are variant in Swift, including Array<T> and Set<T>. Most other types, and the types you define, are invariant.
Invariance means that T<A> and T<B> are unrelated types even if A and B are related.
Array<T> and Set<T> are covariant, which means that a Array<A> can be assigned to a variable of type Array<B> if A is a subtype of B. You can force it to go the other way (like you did in the third line) by using as!.
ArraySlice<T>, like many other types, is simply invariant. You need to do this to convert:
let d: ArraySlice<Int> = ArraySlice(b.map { $0 as! Int })
As an addendum answer to the correct answer by #Sweeper for people who are looking for type-flexible performant copy-by-ref arrays, I ended up rolling a solution which wraps an array in a class and exposes some of the API for an array.
Not a great solution, but it does what I need it to. Boo Apple for not keeping their APIs for this sort of thing consistent.
class ArrayReference<T>: Collection {
private(set) var array : Array<T>
init(_ encapsulating: Array<T>? = nil) {
self.array = encapsulating ?? []
}
var startIndex: Int {
get {
return array.startIndex
}
}
var endIndex: Int {
get {
return array.endIndex
}
}
var count : Int {
get {
return array.count
}
}
func index(after i: Int) -> Int {
return array.index(after: i)
}
subscript (index: Int) -> T {
get { return array[index] }
set(newValue) { array[index] = newValue }
}
func append(_ newValue: T) {
array.append(newValue)
}
func removeAll() {
array.removeAll()
}
var first: T? {
if array.count > 0 {
return array[0]
} else {
return nil
}
}
var last: T? {
if array.count > 0 {
return array[array.count - 1]
} else {
return nil
}
}
func asType<C>(_ type: C.Type) -> ArrayReference<C>? {
if let array = self.array as? Array<C> {
return ArrayReference<C>(array)
} else {
return nil
}
}
}
extension ArrayReference: Equatable where T: Equatable {
static func == (lhs: ArrayReference<T>, rhs: ArrayReference<T>) -> Bool {
if lhs.count == rhs.count {
var equal = true
for (lhs, rhs) in zip(lhs, rhs) {
equal = equal && (lhs == rhs)
}
return equal
} else {
return false
}
}
}
I have an array of objects like this, but with 16 properties:
class anObject: NSObject {
#objc var number: Int
#objc var name: String
#objc var price: Double
subscript(key: String) -> Any? {
return self.value(forKey: key)
}
}
I am able to sort my array on any property very easily by, for instance:
sortedArray = unsortedArray.sorted(by: { $0.name < $1.name } )
Now I am grouping my array so that I can populate a UITableView with sections and rows. I group it like this:
var groupedArray = Dictionary<String, Array<myObject>>()
for item in myArray {
// Verify each grouping is initialized only once
if groupedArray[item[byProperty] as! String] == nil {
groupedArray[item[byProperty] as! String] = Array<Items>()
}
// Add the item into the correct subarray
groupedArray[item[byProperty] as! String]?.append(item)
}
I can then sort the grouped array by doing this:
return groupedArray.sorted { $0.0 < $1.0 }
And this works great, except that two of my properties are Doubles. When I sort on those two properties, Swift sorts the groups alphabetically:
10.5, 11.5, 12, 1.5, 2.0 . . .
rather than numerically
1.5, 2.0, 10.5, 11.5, 12 . . .
I have managed to pad the Doubles by checking to see if they are too short and inserting a 0 at the front of the String. This works in that they are now sorted in correct order, but eventually I am going to have to strip that leading 0 off the front, and it seems like an ugly solution.
How do I properly sort the grouped array given that the Doubles have to be used as Strings?
When you start casting strings all over the place, you likely need to start changing the design of things. Why not make the dictionary keys some object you've designed instead of a string? This is a sample of what I mean:
struct DoubleKey {
let value: Double
}
extension DoubleKey: Hashable {
var hashValue: Int {
return value.hashValue
}
static func ==(lhs: DoubleKey, rhs: DoubleKey) -> Bool {
return lhs.value == rhs.value
}
}
extension DoubleKey: Comparable {
static func <(lhs: DoubleKey, rhs: DoubleKey) -> Bool {
return lhs.value < rhs.value
}
}
let a = DoubleKey(value: 10.0)
let b = DoubleKey(value: 20.0)
let c = DoubleKey(value: -10.0)
let dictionary: [DoubleKey: String] = [a: "10", b: "20", c: "-10"]
let sortedDictionary = dictionary.sorted { $0.0 < $1.0 }
So instead of [String: Array<myobject>] you have: [DoubleKey: Array<MyObject> or [IntegerKey: Array<MyObject>] or even [StringKey: Array<MyObject>
You could implement many variations of your own specialized key, and write some protocols if you need additional functionality. If you need to store a string in your key, then add a property, or better yet, conform it to a protocol that defines the behavior of what you need and implement it.
Additional Key
struct StringKey {
let value: String
}
extension StringKey: Hashable {
var hashValue: Int {
return value.hashValue
}
static func ==(lhs: StringKey, rhs: StringKey) -> Bool {
return lhs.value == rhs.value
}
}
extension StringKey: Comparable {
static func <(lhs: StringKey, rhs: StringKey) -> Bool {
return lhs.value < rhs.value
}
}
let a = StringKey(value: "a")
let b = StringKey(value: "c")
let c = StringKey(value: "b")
let dictionary: [StringKey: String] = [a: "10", b: "20", c: "-10"]
let sortedDictionary = dictionary.sorted { $0.0 < $1.0 }
Now what?
//EXAMPLE
protocol ViewableString {
func view() -> String
}
extension StringKey: ViewableString {
func view() -> String {
return value
}
}
extension DoubleKey: ViewableString {
func view() -> String {
return String(value)
}
}
let array: [ViewableString] = [a, b, c]
array[0].view()
Program to the protocols!
Hopefully this helps!
Ok. Completely different answer. Again, you are trying to fit many objects of different types in the same container. This feels like a bad idea to me. Maybe you have to. But here is one way using enums:
enum SpecialKey {
case integer(Int)
case double(Double)
case string(String)
func asString() -> String {
switch self {
case let .integer(a):
return String(a)
case let .double(a):
return String(a)
case let .string(a):
return a
}
}
}
extension SpecialKey: Comparable {
static func <(lhs: SpecialKey, rhs: SpecialKey) -> Bool {
switch (lhs, rhs) {
case let (.double(a), .double(b)):
return a < b
case let (.integer(a), .integer(b)):
return a < b
case let (.string(a), .string(b)):
return a < b
default:
return false //Add more cases with different comparisons!
}
}
static func ==(lhs: SpecialKey, rhs: SpecialKey) -> Bool {
switch (lhs, rhs) {
case (.integer(_), .integer(_)),
(.double(_), .double(_)),
(.string(_), .string(_)):
return true
default:
return false
}
}
}
extension SpecialKey: Hashable {
var hashValue: Int {
switch self {
case let .integer(a):
return a.hashValue
case let .double(a):
return a.hashValue
case let .string(a):
return a.hashValue
}
}
}
let a = SpecialKey.integer(10)
let b = SpecialKey.string("something")
let c = SpecialKey.double(10.5)
let dictionary: [SpecialKey: String] = [a: "a", b: "b", c: "c"]
This is probably more like what you're looking for.
in GO, I've tried to produce the following json :
[["my",257.14,257.24],["txt", 121.11, 65.555]]
from a struct that's undergo unmarshaling - and i'm failing to do so.
Here is what I tried:
x := []MyStruct{{Zero: map[int]string{0: "str"}, One: map[int]float32{1: 5.6}, Two: map[int]float32{1: 5.88}}}
where MyStruct is :
type Timestamp struct {
Zero map[int]string `json:"0"`
One map[int]float32 `json:"1"`
Two map[int]float32 `json:"2"`
}
this produces the wrong json structure:
"myStruct":[{"0":{"0":"has"},"1":{"1":5.6},"2":{"1":5.88}}]
tried this as well
any clue in the right direction will be highly appreciated.
Maybe this is your expected. It's possible to implement custom MarshalJSON/UnmarshalJSON.
package main
import (
"encoding/json"
"errors"
"fmt"
"log"
)
type Timestamp struct {
Zero []string
One []float32
Two []float32
}
func (t *Timestamp) UnmarshalJSON(b []byte) error {
var arr [][3]interface{}
err := json.Unmarshal(b, &arr)
if err != nil {
return nil
}
t.Zero = nil
t.One = nil
t.Two = nil
for _, v := range arr {
if len(v) != 3 {
return errors.New("invalid json")
}
if s, ok := v[0].(string); ok {
t.Zero = append(t.Zero, s)
}
if f, ok := v[1].(float64); ok {
t.One = append(t.One, float32(f))
}
if f, ok := v[2].(float64); ok {
t.Two = append(t.Two, float32(f))
}
}
return nil
}
func (t *Timestamp) MarshalJSON() ([]byte, error) {
var arr [][3]interface{}
var max int
if max < len(t.Zero) {
max = len(t.Zero)
}
if max < len(t.One) {
max = len(t.One)
}
if max < len(t.Two) {
max = len(t.Two)
}
for i := 0; i < max; i++ {
var v [3]interface{}
if i < len(t.Zero) {
v[0] = t.Zero[i]
}
if i < len(t.One) {
v[1] = t.One[i]
}
if i < len(t.Two) {
v[2] = t.Two[i]
}
arr = append(arr, v)
}
return json.Marshal(arr)
}
const j = `[["my",257.14,257.24],["txt", 121.11, 65.555]]`
func main() {
var ts Timestamp
err := json.Unmarshal([]byte(j), &ts)
if err != nil {
log.Fatal(err)
}
b, err := json.Marshal(&ts)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
https://play.golang.org/p/WtVEja1JDY
The problem you are having is you're trying to unmarshal a map, and a map will correlate to a JSON object. Your desired output is a list, so you need to unmarshal an array or a slice to get a list as your values.
Try making an adapter.
Small example:
type Object struct {
Base float32
Radius float32
Height float32
X float32
Y float32
}
func (obj *Object) ToCircle() *Circle {
return &Circle{
Radius: obj.Radius,
X: obj.X,
Y: obj.Y,
}
}
func (obj *Object) ToRectangle() *Rectangle {
return &Rectangle{
Base: obj.Base,
Height: obj.Height,
X: obj.X,
Y: obj.Y,
}
}
In the example above, Object is converted to a Rectangle or a Circle using the ToRectangle() and ToCircle() adapters, respectively. In your case, you need to convert Timestamp to a []interface{}. Then you can unmarshal and you'll just get a list of whatever values are in that slice, which is your desired output in this case.
For intsance, the signature if your adapter could look like this:
func (t *Timestamp) ToFoo() []interface{} {
var ret []interface{}
// Do some stuff to take values of 't' and append to 'ret'
return ret
}
func main() {
var result []interface{}
json.Unmarshal(t.ToFoo(), &result)
// ...
}
I'll leave the implementation details for you.
I want the Struct array to have return values of the Function I defined later in the code.
In here I defined a struct "array" and info is the array of all those values in the struct, I want every element in the info array to have the respective values I mentioned, info.pos should have the value of the string I'm passing through the function PossibleMoves(), info.bitrep should have the return value from the function converttobit(), info.numrep should have the return value of toNumber(), and v1-v8 should have the values of the moves[] array, (v1=moves[0]).
My code is definitely clumsy can someone help?
package main
import ("bufio"
"fmt"
"os"
"strings")
type array struct{
pos string
bitrep int64
numrep,v1,v2,v3,v4,v5,v6,v7,v8 int8
}
func main() {
file, err := os.Open("chessin.txt")
if err != nil {
fmt.Println(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
valid := []bool{}
for scanner.Scan() {
b := strings.Split(scanner.Text(), ",")
valid = append(valid, isvalid(b))
}
fmt.Println(valid)
info :=[64][11]array {
info.pos = Possiblemoves(pos)
info.bitrep=coverttobit(num)
info.numrep=toNumber(string)
info.v0=moves[0]
info.v1=moves[1]
info.v2=moves[2]
info.v3=moves[3]
info.v4=moves[4]
info.v5=moves[5]
info.v6=moves[6]
info.v7=moves[7]
}
}
func convertingtobit( num int){
n := int64(num)
bit:=strconv.FormatInt(n, 2)
}
func isvalid(b string) bool {
if b[0]<='H' && b[0]>='A' && b[1]<='8' && b[1]>='0' {
return true
}
return false
}
func toNumber(s string) int {
if len(s) != 2 {
fmt.Println("Invalid Input",s,".")
}
num=int(s[0]-'A')*8 + int(s[1]-'0')
return num
}
func PossibleMoves(a string) {
isvalid := isvalid(a)
if isvalid == true {
var moves [8]string
moves[0]=string(a[0]+1)+string(a[1]+2)
moves[1]=string(a[0]+1)+string(a[1]-2)
moves[2]=string(a[0]-1)+string(a[1]+2)
moves[3]=string(a[0]-1)+string(a[1]-2)
moves[4]=string(a[0]+2)+string(a[1]+1)
moves[5]=string(a[0]+2)+string(a[1]-1)
moves[6]=string(a[0]-2)+string(a[1]+1)
moves[7]=string(a[0]-2)+string(a[1]-1)
fmt.Println("Possible moves are : ",moves)
var PosMoves [8] int
for i:=0;i<8;i++ {
if isvalid == true {
PosMoves[i]=toNumber(moves[i])
}
}
fmt.Println("After converting : ",PosMoves)
} else {
fmt.Println("Invalid Input")
}
}
Short Answer ( Compile: Success) :
package main
import "fmt"
type array struct {
pos string
bitrep int64
numrep, v1, v2, v3, v4, v5, v6, v7, v8 int8
}
func toNumber(s string) int8 {
if len(s) != 2 {
fmt.Println("Invalid Input", s, ".")
}
num := int8(s[0]-'A')*8 + int8(s[1]-'0')
return num
}
func PossibleMoves(out *array, a string) {
out.v1 = toNumber(string(a[0]+1) + string(a[1]+2))
}
func main() {
info := &array{
pos: "A1",
bitrep: 1,
}
PossibleMoves(info, "")
}
There are some problems:
1- in your code use := instead of = for new vars:
func toNumber(s string) int {
if len(s) != 2 {
fmt.Println("Invalid Input",s,".")
}
num=int(s[0]-'A')*8 + int(s[1]-'0')
return num
}
Like this:
func toNumber(s string) int {
if !isvalid(s) {
panic("Invalid Input" + s + ".")
}
num := int(s[0]-'A')*8 + int(s[1]-'0')
return num
}
2- your code:
func isvalid(b string) bool {
if b[0]<='H' && b[0]>='A' && b[1]<='8' && b[1]>='0' {
return true
}
return false
}
check for len(b) == 2 like this:
func isvalid(b string) bool {
if len(b) == 2 && b[0] <= 'H' && b[0] >= 'A' && b[1] <= '8' && b[1] >= '1' {
return true
}
return false
}
3- try not to copy paste:
moves[0]=string(a[0]+1)+string(a[1]+2)
moves[1]=string(a[0]+1)+string(a[1]-2)
moves[2]=string(a[0]-1)+string(a[1]+2)
moves[3]=string(a[0]-1)+string(a[1]-2)
moves[4]=string(a[0]+2)+string(a[1]+1)
moves[5]=string(a[0]+2)+string(a[1]-1)
moves[6]=string(a[0]-2)+string(a[1]+1)
moves[7]=string(a[0]-2)+string(a[1]-1)
Answering exact question:
type array struct{
pos string
bitrep int64
numrep,v1,v2,v3,v4,v5,v6,v7,v8 int8
}
func PossibleMoves(out *array, a string) {
out.v1 = tonumber(string(a[0]+1) + string(a[1]+2))
// ...
}
func main() {
// ...
info := &array{
pos: "...",
bitrep: 1234,
}
PossibleMoves(info, line)
}
But instead of this small detail, concentrate on answer by #Amd.
How would I go about implementing a custom enumerate function that makes something like this work (Swift 2):
for ((column, row), item) in Array2D.enumerate() { ... }
In my simple Array2D struct:
struct Array2D<T> : SequenceType {
let columns: Int
let rows: Int
private var array: Array<T?>
init(columns: Int, rows: Int) {
self.columns = columns
self.rows = rows
array = Array(count: rows*columns, repeatedValue: nil)
}
subscript(column: Int, row: Int) -> T? {
get {
return array[columns*row + column]
}
set {
array[columns*row + column] = newValue
}
}
func generate() -> AnyGenerator<T?> {
var column = 0
var row = 0
return anyGenerator() {
guard row < self.rows else {
return nil
}
let item = self[column, row]
if ++column == self.columns {
column = 0
++row
}
return item
}
}
}
I couldn't find any good explanation on implementing an enumerate function in Swift
The enumerate() function in Swift returns integers starting from 0 for the first part of its tuple. Those have nothing to do with the sequence you're enumerating over. So, for instance, this won't work:
let word = "hello".characters
for (index, letter) in word.enumerate() {
print(word[index])
}
Because the indices of a characterView are String.Indexs.
So there are several ways to get what you're going for. The first is to just overload enumerate() for your struct. Again, there are a few days you could do this. First off, how about a function that uses your own generator, and uses its own logic to figure out the coordinates. This could work:
func enumerate() -> AnyGenerator<((Int, Int), T?)> {
let g = self.generate()
var coord = -1
return anyGenerator {
g.next().map { ((++coord % self.columns, coord / self.columns), $0) }
}
}
But you're duplicating code there, especially from your generate method. Seeing you're already using coordinates to return each element, why not just have your enumerate method be the default, and your generate method call on that. Something like this:
// Original generate method, now returns the coords it used
func enumerate() -> AnyGenerator<((Int, Int), T?)> {
var column = 0
var row = 0
return anyGenerator() {
guard row < self.rows else {
return nil
}
let item = self[column, row]
if ++column == self.columns {
column = 0
++row
}
return ((column, row), item)
}
}
// uses enumerate, ignores coords
func generate() -> AnyGenerator<T?> {
let g = self.enumerate()
return anyGenerator {
g.next().map { $1 }
}
}
If you wanted to go a little overboard, you could write an enumerate function that enumerates the specific indices of its base. Call it specEnumerate:
public struct SpecEnumerateGen<Base : CollectionType> : GeneratorType {
private var eG: Base.Generator
private let sI: Base.Index
private var i : Base.Index?
public mutating func next() -> (Base.Index, Base.Generator.Element)? {
i?._successorInPlace() ?? {self.i = self.sI}()
return eG.next().map { (i!, $0) }
}
private init(g: Base.Generator, i: Base.Index) {
self.eG = g
self.sI = i
self.i = nil
}
}
public struct SpecEnumerateSeq<Base : CollectionType> : SequenceType {
private let col: Base
public func generate() -> SpecEnumerateGen<Base> {
return SpecEnumerateGen(g: col.generate(), i: col.startIndex)
}
}
public extension CollectionType {
func specEnumerate() -> SpecEnumerateSeq<Self> {
return SpecEnumerateSeq(col: self)
}
}
With this function, this would work:
let word = "hello".characters
for (index, letter) in word.specEnumerate() {
print(word[index])
}
But your matrix struct is still a SequenceType, with no specific indices. For that, you'll have to implement your own MatrixIndex:
public struct MatrixIndex: BidirectionalIndexType {
public let x, y : Int
private let columns: Int
public func successor() -> MatrixIndex {
return (x + 1 == columns) ?
MatrixIndex(x: 0, y: y + 1, columns: columns) :
MatrixIndex(x: x + 1, y: y, columns: columns)
}
public func predecessor() -> MatrixIndex {
return (x == 0) ?
MatrixIndex(x: columns - 1, y: y - 1, columns: columns) :
MatrixIndex(x: x - 1, y: y, columns: columns)
}
}
public func == (lhs: MatrixIndex, rhs: MatrixIndex) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
extension MatrixIndex : CustomDebugStringConvertible {
public var debugDescription: String {
return "\(x), \(y)"
}
}
extension MatrixIndex: RandomAccessIndexType {
public func advancedBy(n: Int) -> MatrixIndex {
let total = (y * columns) + x + n
return MatrixIndex(x: total % columns, y: total / columns, columns: columns)
}
public func distanceTo(other: MatrixIndex) -> Int {
return (other.x - x) + (other.y - y) * columns
}
}
Right. Now you'll need another matrix struct:
public struct Matrix2D<T> : MutableCollectionType {
public var contents: [[T]]
public subscript(index: MatrixIndex) -> T {
get {
return contents[index.y][index.x]
} set {
self.contents[index.y][index.x] = newValue
}
}
public var count: Int { return contents[0].count * contents.count }
public var startIndex: MatrixIndex {
return MatrixIndex(x: 0, y: 0, columns: contents[0].count)
}
public var endIndex: MatrixIndex {
return MatrixIndex(x: 0, y: contents.endIndex, columns: contents[0].count)
}
}
Right. So now, after all of that, this works:
let myMatrix = Matrix2D(contents: [[1, 2], [3, 4]])
for (coordinate, value) in myMatrix.specEnumerate() {
value == myMatrix[coordinate] // True every time
}
It might suffice defining your own enumerate taking advantage of the one you already have:
func enumerate() -> AnyGenerator<((Int, Int), T?)> {
var index = 0
var g = array.generate()
return anyGenerator() {
if let item = g.next() {
let column = index % self.columns
let row = index / self.columns
++index
return ((column, row) , item)
}
return nil
}
}
Notice in this case you could avoid conforming to SequenceType since I use generate from the private array. Anyway it could be consistent to do so.
Here is how then you could use it:
var a2d = Array2D<Int>(columns: 2, rows: 4)
a2d[0,1] = 4
for ((column, row), item) in a2d.enumerate() {
print ("[\(column) : \(row)] = \(item)")
}
Hope this helps