2017-03-15 10 views
0

Ich erhalte derzeit einen Int, der zwischen 0 und 180.000 liegen könnte. Ich brauche es zu ändern zu passen zwischen 0 und 3000. I in anderen Sprachen kennen Sie so etwas wieWie interpoliere ich von einer Zahl in einem Bereich zu einem entsprechenden Wert in einem anderen Bereich?

Map(min1,max1,min2,max2,input) 

Ich kann nicht scheinen, etwas wie das Innere des schnellen suchen können. Dies ist, was ich zur Zeit habe, aber es gibt immer 0.

var newY = [(Int)(input)] 
newY = newY.map {_ in 0 * 3000} 
print(newY[0]) 

Ich denke, dass ich die falsche Funktion verwenden. Ich habe noch nie in Swift ein Mapping durchgeführt.

+0

http://stackoverflow.com/questions/24132399/how-does-one-make-random-number-between-range-for-arc4random -uniform – Sahil

+0

Was bedeutet "eine Zahl zwischen zwei Zahlen halten"? Möchten Sie eine Zufallszahl generieren? –

+0

Ihre Frage ist unklar, aber die Dokumentation zu 'map' finden Sie [hier] (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html). – Caleb

Antwort

2

Die map Funktion auf Sammlungen wird etwas ganz anderes tun. Es wendet eine Zuordnungsfunktion auf jedes Element einer Auflistung an und gibt basierend auf den Ergebnissen eine neue Auflistung zurück.

Was Sie suchen wäre:

func map(minRange:Int, maxRange:Int, minDomain:Int, maxDomain:Int, value:Int) -> Int { 
    return minDomain + (maxDomain - minDomain) * (value - minRange)/(maxRange - minRange) 
} 

print(map(minRange: 0, maxRange: 1800000, minDomain: 0, maxDomain: 3000, value: 200000)) 

Mit nur ein wenig mehr Arbeit, die Sie es generic über alle Integer-Typen machen:

func map<T:IntegerArithmetic>(minRange:T, maxRange:T, minDomain:T, maxDomain:T, value:T) -> T { 
    return minDomain + (maxDomain - minDomain) * (value - minRange)/(maxRange - minRange) 
} 

Eine weitere Option wäre zu nutzen

func map<T:IntegerArithmetic>(range:Range<T>, domain:Range<T>, value:T) -> T { 
    return domain.lowerBound + (domain.upperBound - domain.lowerBound) * (value - range.lowerBound)/(range.upperBound - range.lowerBound) 
} 

map(range:0..<3000, domain:0..<180000, value: 1500) 
+0

Es gibt einen wesentlichen Unterschied zwischen dfris Antwort und mir darin, dass aufgrund der Reihenfolge der Operationen wird mein eine gleichmäßigere Verteilung haben, während es weniger wahrscheinlich ist, dass es zu Überläufen kommt. Alles hängt davon ab, was Sie suchen. –

+1

Wäre es nicht besser, einen anderen Namen der neuen Funktion vorzuschlagen, um eine Verwechslung mit der vorhandenen 'Karte' zu ​​vermeiden ? –

+0

Wahrscheinlich behielt ich nur seinen Namen intakt. –

0

Vorausgesetzt, dass Sie für die Zuordnung der relativen Position eines Wertes in einem bestimmten Bereich in einen anderen Bereich suchen, können Sie etwas entlang der Linien tun könnte:

// dummy function name 
func transform(_ number: Int, fromRange: (Int, Int), toRange: (Int, Int)) -> Int? { 
    guard number >= fromRange.0 && number <= fromRange.1, 
     toRange.0 <= toRange.1 else { return nil } 
    return toRange.0 + (number-fromRange.0)*(toRange.1-toRange.0)/(fromRange.1-fromRange.0) 
} 

// ex1 
let numberA = 3001 
let transformedNumberA = transform(numberA, fromRange: (0, 180_000), toRange: (0,3000)) 
print(transformedNumberA ?? -1) // 50 

// ex2 
let numberB = 134_000 
let transformedNumberB = transform(numberB, fromRange: (0, 180_000), toRange: (0,3000)) 
print(transformedNumberB ?? -1) // 2233 

// ex3 
let numberC = 200_000 
let transformedNumberC = transform(numberC, fromRange: (0, 180_000), toRange: (0,3000)) 
print(transformedNumberC ?? -1) // -1 (nil return) 

Nur kümmern zu bemerken, dass (number-fromRange.0)*(toRange.1-toRange.0) (links Assoziativität von / und * Operatoren) kann überlaufen.

+0

Sie müssen die subtrahieren Minimum Eingabebereich Wert vor Mathematik, sonst funktioniert es nur, wenn der Eingabebereich bei Null beginnt. –

+0

@DavidBerry: Sie haben Recht, danke! – dfri

0

: von der Art Swift Range zu prägnanter machen das telefonieren Es ist nicht klar, ob das OP einfach klemmen will (der Titel scheint das zu sagen) oder von einem Grenzbereich zum anderen interpolieren will. Der Titel lässt mich einen denken, aber die doppelten Max/Min-Werte lassen mich denken, dass sie nach einer Interpolation sind. Ich antwortete dem ehemaligen. David Berry hat eine gute Antwort für Letzteres.

Was Sie können wollen ist Min/Max-Funktionen. Swift hat diese. Um „klemmen“ einen Wert zwischen einem niedrigen und hohen Wert, kombinieren Sie in der Regel die beiden:

var bottom = 13 
var top = 42 
var tooLow = 7 
var clamped = min(top, max(bottom, tooLow)) -> 13 
var justRight = 23 
clamped = min(top, max(bottom, justRight)) --> 23 
var tooHigh = 99 
clamped = min(top, max(bottom, tooHigh)) --> 42 

Dies ist in der Regel der Weg die meisten Menschen gehen, und ist wahrscheinlich gut genug für die meisten. Ich persönlich hasse es, das immer wieder zu schreiben, und ich habe es satt, darüber nachdenken zu müssen, auf welcher Seite ich mich in das Max und das Min einspeisen soll. Und Ich mag es nicht, dass es verwendet, was wie eine freie Funktion sieht, ich bin eine objektorientierte Nachricht Art von Kerl zu senden, so dass ich wie folgt vorgehen:

precedencegroup MinMaxPrecedence { 
    associativity: left 
    higherThan: NilCoalescingPrecedence, AdditionPrecedence, MultiplicationPrecedence 
} 

infix operator <> : MinMaxPrecedence 

func <><T:Comparable>(a:T, b:T) -> T { 
    return a < b ? a : b 
} 

infix operator >< : MinMaxPrecedence 

func ><<T:Comparable>(a:T, b:T) -> T { 
    return a < b ? b : a 
} 

Im Grunde ist dies definiert zwei neue Operatoren (<> und ><), die zwischen jedem Typ verwendet werden kann, der Comparable annimmt. Sie sind für mich leicht zu merken, derjenige, der sich kleiner einfügt, will den kleineren Wert, und derjenige, der größer öffnet, gibt den größeren Wert zurück.Was schön ist, dass man sie dann in einfacher Ausdrücke setzen können:

var bottom = 13 
var top = 42 
var tooLow = 7 
var justRight = 23 
var tooHigh = 99 
bottom >< tooLow <> top --> 13 
bottom >< justRight <> top --> 23 
bottom >< tooHigh <> top --> 42 
+0

Obwohl ich zustimme, ist es nicht absolut klar, seine "Map" -Funktion benötigt zwei Bereiche, was bedeutet, dass er eigentlich interpolieren möchte. Kombinieren Sie das, nachdem Sie irgendwo eine 'map'-Funktion gesehen haben, die genau das tut, scheint es wahrscheinlich, dass sie das wirklich wollen. –

+0

Yup, erkannte, dass wahrscheinlich nach dem Schreiben aller oben genannten war. :( –

Verwandte Themen