Objective C 距离字符串格式化程序

发布于 2024-08-22 12:28:02 字数 350 浏览 11 评论 0原文

我有一个距离作为浮动,我正在寻找一种方法来为人类读者很好地格式化它。理想情况下,我希望随着它变大,它从 m 变为 km,并很好地舍入数字。转换成里程将是一个额外的好处。我确信很多人都需要其中之一,我希望有一些代码在某个地方。

以下是我想要的格式:

  • 0-100m:47m(作为整数)
  • 100-1000m:325m 或 320m(四舍五入到最接近的 5 或 10 米)
  • 1000-10000m:1.2km(四舍五入到最接近的小数点后一位) place)
  • 10000m +: 21km

如果没有可用的代码,我如何编写自己的格式化程序?

谢谢

I have a distance as a float and I'm looking for a way to format it nicely for human readers. Ideally, I'd like it to change from m to km as it gets bigger, and to round the number nicely. Converting to miles would be a bonus. I'm sure many people have had a need for one of these and I'm hoping that there's some code floating around somewhere.

Here's how I'd like the formats:

  • 0-100m: 47m (as a whole number)
  • 100-1000m: 325m or 320m (round to the nearest 5 or 10 meters)
  • 1000-10000m: 1.2km (round to nearest with one decimal place)
  • 10000m +: 21km

If there's no code available, how can I write my own formatter?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

画离情绘悲伤 2024-08-29 12:28:02

这些解决方案都没有真正满足我的需求,所以我在它们的基础上进行了构建:

#define METERS_TO_FEET  3.2808399
#define METERS_TO_MILES 0.000621371192
#define METERS_CUTOFF   1000
#define FEET_CUTOFF     3281
#define FEET_IN_MILES   5280

- (NSString *)stringWithDistance:(double)distance {
    BOOL isMetric = [[[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem] boolValue];

    NSString *format;

    if (isMetric) {
        if (distance < METERS_CUTOFF) {
            format = @"%@ metres";
        } else {
            format = @"%@ km";
            distance = distance / 1000;
        }
    } else { // assume Imperial / U.S.
        distance = distance * METERS_TO_FEET;
        if (distance < FEET_CUTOFF) {
            format = @"%@ feet";
        } else {
            format = @"%@ miles";
            distance = distance / FEET_IN_MILES;
        }
    }

    return [NSString stringWithFormat:format, [self stringWithDouble:distance]];
}

// Return a string of the number to one decimal place and with commas & periods based on the locale.
- (NSString *)stringWithDouble:(double)value {
    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setLocale:[NSLocale currentLocale]];
    [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [numberFormatter setMaximumFractionDigits:1];
    return [numberFormatter stringFromNumber:[NSNumber numberWithDouble:value]];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    double distance = 5434.45;
    NSLog(@"%f meters is %@", distance, [self stringWithDistance:distance]);

    distance = 543.45;
    NSLog(@"%f meters is %@", distance, [self stringWithDistance:distance]);    

    distance = 234234.45;
    NSLog(@"%f meters is %@", distance, [self stringWithDistance:distance]);    
}

None of these solutions really met what I was looking for, so I built on them:

#define METERS_TO_FEET  3.2808399
#define METERS_TO_MILES 0.000621371192
#define METERS_CUTOFF   1000
#define FEET_CUTOFF     3281
#define FEET_IN_MILES   5280

- (NSString *)stringWithDistance:(double)distance {
    BOOL isMetric = [[[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem] boolValue];

    NSString *format;

    if (isMetric) {
        if (distance < METERS_CUTOFF) {
            format = @"%@ metres";
        } else {
            format = @"%@ km";
            distance = distance / 1000;
        }
    } else { // assume Imperial / U.S.
        distance = distance * METERS_TO_FEET;
        if (distance < FEET_CUTOFF) {
            format = @"%@ feet";
        } else {
            format = @"%@ miles";
            distance = distance / FEET_IN_MILES;
        }
    }

    return [NSString stringWithFormat:format, [self stringWithDouble:distance]];
}

// Return a string of the number to one decimal place and with commas & periods based on the locale.
- (NSString *)stringWithDouble:(double)value {
    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setLocale:[NSLocale currentLocale]];
    [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [numberFormatter setMaximumFractionDigits:1];
    return [numberFormatter stringFromNumber:[NSNumber numberWithDouble:value]];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    double distance = 5434.45;
    NSLog(@"%f meters is %@", distance, [self stringWithDistance:distance]);

    distance = 543.45;
    NSLog(@"%f meters is %@", distance, [self stringWithDistance:distance]);    

    distance = 234234.45;
    NSLog(@"%f meters is %@", distance, [self stringWithDistance:distance]);    
}
后eg是否自 2024-08-29 12:28:02

iOS 7 和 OS X 10.9 引入了 MKDistanceFormatter 用于格式化距离:

代码示例:

double myDistance = 21837.0f;

MKDistanceFormatter *df = [[MKDistanceFormatter alloc]init];
df.unitStyle = MKDistanceFormatterUnitStyleAbbreviated;

NSLog(@"myDistance is %@", [df stringFromDistance: myDistance]);

更新:

MKDistanceFormatter 似乎以某种方式对输入值进行舍入。例如,当我将 myDistance 设置为 111.0 时,我得到“100 m”。

iOS 7 and OS X 10.9 introduced MKDistanceFormatter for formatting distances:

Code Example:

double myDistance = 21837.0f;

MKDistanceFormatter *df = [[MKDistanceFormatter alloc]init];
df.unitStyle = MKDistanceFormatterUnitStyleAbbreviated;

NSLog(@"myDistance is %@", [df stringFromDistance: myDistance]);

Update:

It seems that MKDistanceFormatter is rounding the input value somehow. E.g. when I set myDistance to 111.0 I get "100 m".

萌酱 2024-08-29 12:28:02

是的,你需要编写自己的格式化程序,例如

#include <math.h>
NSString* convertDistanceToString(float distance) {
    if (distance < 100)
       return [NSString stringWithFormat:@"%g m", roundf(distance)];
    else if (distance < 1000)
       return [NSString stringWithFormat:@"%g m", roundf(distance/5)*5];
    else if (distance < 10000)
       return [NSString stringWithFormat:@"%g km", roundf(distance/100)/10];
    else
       return [NSString stringWithFormat:@"%g km", roundf(distance/1000)];
}
...
NSLog(@"The distance is %@", convertDistanceToString(1024));

Yes you need to write your own formatter, like

#include <math.h>
NSString* convertDistanceToString(float distance) {
    if (distance < 100)
       return [NSString stringWithFormat:@"%g m", roundf(distance)];
    else if (distance < 1000)
       return [NSString stringWithFormat:@"%g m", roundf(distance/5)*5];
    else if (distance < 10000)
       return [NSString stringWithFormat:@"%g km", roundf(distance/100)/10];
    else
       return [NSString stringWithFormat:@"%g km", roundf(distance/1000)];
}
...
NSLog(@"The distance is %@", convertDistanceToString(1024));
扬花落满肩 2024-08-29 12:28:02

NSLengthFormatter 其中随着 iOS 8 和 OS X 10.10 的推出,人们应该意识到这一选项。

    NSLengthFormatter *lengthFormatter = [[NSLengthFormatter alloc] init];
    lengthFormatter.unitStyle = NSFormattingUnitStyleShort;

    NSLog(@"distance = %@", [lengthFormatter stringFromMeters:meters]);

但是,NSLengthFormatter 在使用公制(距离除外)的区域设置中不使用英制单位。

NSLengthFormatter which was introduced with iOS 8 and OS X 10.10 is an option people should be aware of.

    NSLengthFormatter *lengthFormatter = [[NSLengthFormatter alloc] init];
    lengthFormatter.unitStyle = NSFormattingUnitStyleShort;

    NSLog(@"distance = %@", [lengthFormatter stringFromMeters:meters]);

However, NSLengthFormatter has doesn't use Imperial units in those locales where they use metric except for distances.

探春 2024-08-29 12:28:02

我是这样做的。这使用用户的区域设置来正确格式化字符串,您可能也应该这样做。

// Returns a string representing the distance in the correct units.
// If distance is greater than convert max in feet or meters, 
// the distance in miles or km is returned instead
NSString* getDistString(float distance, int convertMax, BOOL includeUnit) {
  NSString * unitName;
  if (METRIC) {
    unitName = @"m";
    if (convertMax != -1 && distance > convertMax) {
      unitName = @"km";
      distance = distance / 1000;
    }
  } else {
    unitName = @"ft";
    if (convertMax != -1 && distance > convertMax) {
      unitName = @"mi";
      distance = distance / 5280;
    }
    distance = metersToFeet(distance);
  }

  if (includeUnit) return [NSString stringWithFormat:@"%@ %@", formatDecimal_1(distance), unitName];

  return formatDecimal_1(distance);

}
// returns a string if the number with one decimal place of precision
// sets the style (commas or periods) based on the locale
NSString * formatDecimal_1(float num) {
  static NSNumberFormatter *numFormatter;
  if (!numFormatter) {
    numFormatter = [[[NSNumberFormatter alloc] init] retain];
    [numFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
    [numFormatter setLocale:[NSLocale currentLocale]];
    [numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [numFormatter setMaximumFractionDigits:1];
    [numFormatter setMinimumFractionDigits:1];
  }

  return [numFormatter stringFromNumber:F(num)];

}

Here's how I do it. This uses the locale of the user to properly format the string, which you should probably do too.

// Returns a string representing the distance in the correct units.
// If distance is greater than convert max in feet or meters, 
// the distance in miles or km is returned instead
NSString* getDistString(float distance, int convertMax, BOOL includeUnit) {
  NSString * unitName;
  if (METRIC) {
    unitName = @"m";
    if (convertMax != -1 && distance > convertMax) {
      unitName = @"km";
      distance = distance / 1000;
    }
  } else {
    unitName = @"ft";
    if (convertMax != -1 && distance > convertMax) {
      unitName = @"mi";
      distance = distance / 5280;
    }
    distance = metersToFeet(distance);
  }

  if (includeUnit) return [NSString stringWithFormat:@"%@ %@", formatDecimal_1(distance), unitName];

  return formatDecimal_1(distance);

}
// returns a string if the number with one decimal place of precision
// sets the style (commas or periods) based on the locale
NSString * formatDecimal_1(float num) {
  static NSNumberFormatter *numFormatter;
  if (!numFormatter) {
    numFormatter = [[[NSNumberFormatter alloc] init] retain];
    [numFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
    [numFormatter setLocale:[NSLocale currentLocale]];
    [numFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [numFormatter setMaximumFractionDigits:1];
    [numFormatter setMinimumFractionDigits:1];
  }

  return [numFormatter stringFromNumber:F(num)];

}
撧情箌佬 2024-08-29 12:28:02

今天发现这个问同样的问题....going with :

 NSString *rvalue;
    if (value > 1000) {
        rvalue = [NSString stringWithFormat:@"%.02f km",value];
    }else {
        rvalue = [NSString stringWithFormat:@"%.02f m",value];
    }

如果需要的话可以将其包装在一个方法中

found this today asking the same question....going with :

 NSString *rvalue;
    if (value > 1000) {
        rvalue = [NSString stringWithFormat:@"%.02f km",value];
    }else {
        rvalue = [NSString stringWithFormat:@"%.02f m",value];
    }

could wrap this in a method, if need be

憧憬巴黎街头的黎明 2024-08-29 12:28:02

对于那些正在寻找 swift 2.0 版本的人。移植自@MattDiPasquale

 extension Double {
  func toDistanceString() -> String {
    let METERS_TO_FEET = 3.2808399
    let METERS_CUTOFF = 1000.0
    let FEET_CUTOFF = 3281.0
    let FEET_IN_MILES =  5280.0

    let format:String
    if (NSLocale.isMetric()) {
      if (self < METERS_CUTOFF) {
        format = "\(self.stringWithDecimals(0)) metres"
      } else {
        format = "\((self / 1000).stringWithDecimals(1)) km";
      }
    } else { // assume Imperial / U.S.
      let feet = self * METERS_TO_FEET;
      if (feet < FEET_CUTOFF) {
        format = "\(feet.stringWithDecimals(0)) feet";
      } else {
        format = "\((self / FEET_IN_MILES).stringWithDecimals(1)) miles";
      }
    }
    return format
  }

  func stringWithDecimals(decimals:Int) -> String {
    return String(format: "%.\(decimals)f", self)
  }
}

extension NSLocale {
  class func isMetric() -> Bool {
    let locale = NSLocale.currentLocale()
    return locale.objectForKey(NSLocaleUsesMetricSystem) as! Bool
  }
}

For those looking for a swift 2.0 version. Ported from @MattDiPasquale

 extension Double {
  func toDistanceString() -> String {
    let METERS_TO_FEET = 3.2808399
    let METERS_CUTOFF = 1000.0
    let FEET_CUTOFF = 3281.0
    let FEET_IN_MILES =  5280.0

    let format:String
    if (NSLocale.isMetric()) {
      if (self < METERS_CUTOFF) {
        format = "\(self.stringWithDecimals(0)) metres"
      } else {
        format = "\((self / 1000).stringWithDecimals(1)) km";
      }
    } else { // assume Imperial / U.S.
      let feet = self * METERS_TO_FEET;
      if (feet < FEET_CUTOFF) {
        format = "\(feet.stringWithDecimals(0)) feet";
      } else {
        format = "\((self / FEET_IN_MILES).stringWithDecimals(1)) miles";
      }
    }
    return format
  }

  func stringWithDecimals(decimals:Int) -> String {
    return String(format: "%.\(decimals)f", self)
  }
}

extension NSLocale {
  class func isMetric() -> Bool {
    let locale = NSLocale.currentLocale()
    return locale.objectForKey(NSLocaleUsesMetricSystem) as! Bool
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文