Scala:如何在要在其他方法中使用的方法中将多个函数结果作为元组返回

时间:2017-06-12 12:28:03

标签: scala methods functional-programming tuples

我是Scala和功能编程的新手。我正忙着将Python(程序)模块重写为Scala对象类。我被困在需要定义一个方法(ExtractTime)的地方,该方法接受String和Map(Dictionary)作为参数,并根据方法中的val函数结果将结果作为元组返回。我在方法中有三个函数返回“Hours”,“Minutes”,“Period”。我收到的错误消息是返回类型是“Unit”,所需的输出是(Int,Int,String)。如何将“ExtractTime”方法中的值作为元组返回,请注意输出类型不相同(即Int,Int,String)。

package Time

/**
  * Created by PeterW on 6/11/2017.
  */
object TimeAsWords2 extends App {

  // Input string argument is based on 24hr format 23:59
  val InputTime = args(0)

  // regular expression string
  val Exp24hr = """^(([01]\d|2[0-3]):([0-5]\d)|23:59)$"""

  // a Map of word equivalent of integer values
  val WordsLookup = Map(1 -> "one", 2 -> "two", 3 -> "three", 4 -> "four",
    5 -> "five", 6 -> "six", 7 -> "seven", 8 -> "eight",
    9 -> "nine", 10 -> "ten", 11 -> "eleven", 12 -> "twelve",
    13 -> "thirteen", 14 -> "fourteen", 16 -> "sixteen",
    17 -> "seventeen", 18 -> "eighteen", 19 -> "nineteen",
    20 -> "twenty", 21 -> "twenty one", 22 -> "twenty two",
    23 -> "twenty three", 24 -> "twenty four", 25 -> "twenty five",
    26 -> "twenty six", 27 -> "twenty seven", 28 -> "twenty eight",
    29 -> "twenty nine")

  // a Map of time periods
  val PeriodLookup = Map(1 -> "before midday", 2 -> "after midday")


  // main method to covert time in 24hr format to time as words
  def TimeAsWords(InputTime: String, Exp24hr: String,
                  WordsLookup: Map[Int, String], PeriodLookup: Map[Int, String]) = {

    def ExtractTime(InputTime: String, PeriodLookup: Map[Int, String]) : (Int, Int, String) = {
      // extract hours from string
      val HrsInt = InputTime.take(2).toInt
      // convert HrsInt into 12hrs using (12 - ((HrsInt) % 12)
      val Hrs12Int = 12
      // extract minutes from string
      val MinInt = InputTime.takeRight(2).toInt
      // determine PdString (PeriodLookup(2) if HrsInt >= 12 else PeriodLookup(1))
      val PdString = PeriodLookup(1).mkString

      def ConvertTime(Hrs12Int: Int, MinInt: Int, PrString: String) = {
        // convert input hours, minutes and period into time as words
        // based on if else if conditions based on Python module
        // return time as words as a string
      }
      // test if input time matches 24hr format else stop program
      // and return message that format is incorrect
      val pattern24hr = InputTime.matches(Exp24hr)
      if (InputTime.matches(Exp24hr)){
        val (Hrs12Int, MinInt, PdString) = ExtractTime(InputTime, PeriodLookup)
        val TimeWords = ConvertTime(Hrs12Int, MinInt, PdString)
        println(TimeWords)
      } else{
        println("Input time format doesn't match 24hr format: 00:00 - 23:59")
        System.exit(0)
      }
    }
  }
  TimeAsWords(InputTime, Exp24hr, WordsLookup, PeriodLookup)
}

Scala对象:TimeAsWords

enter image description here

Scala方法ExtractTime:错误消息

"""
Created on 28 May 2017

Convert 24hr format time

into time as words

@author: PeterW
"""
import sys
import re
import argparse


def words_lookup():
    """Create a dictionary
    to lookup equivalent word
    of integer number"""
    words_dict = {1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five',
                  6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten',
                  11: 'eleven', 12: 'twelve', 13: 'thirteen',
                  14: 'fourteen', 16: 'sixteen', 17: 'seventeen',
                  18: 'eighteen', 19: 'nineteen', 20: 'twenty',
                  21: 'twenty one', 22: 'twenty two', 23: 'twenty three',
                  24: 'twenty four', 25: 'twenty five', 26: 'twenty six',
                  27: 'twenty seven', 28: 'twenty eight', 29: 'twenty nine'}
    return words_dict


def validate_time_format(input_time):
    """Validate that input string
    matches require 24hr time format"""
    regexp_object = re.compile(r'^(([01]\d|2[0-3]):([0-5]\d)|23:59)$')
    if regexp_object.match(input_time):
        print("Processing: {0} into words".format(input_time))
        time_str = input_time
    else:
        print("{0} doesn't match required input format: 00:00 to 23:59"
              .format(input_time))
        sys.exit()
    return time_str


def extract_time(time_str):
    """Convert time from 24hr format
    into 12hours, minutes and period"""
    period_type = {'am': 'before midday', 'pm': 'after midday'}
    try:
        hours, minutes = int(time_str[:2]), int(time_str[3:])
        suffix = "{0}".format("pm" if hours >= 12 else 'am')
        hours = 12 - ((-hours) % 12)
        period = period_type.get(suffix)
    except ValueError as err:
        print(err)
        sys.exit()
    return hours, minutes, period


def time_conversion(words_dict, hours, minutes, period):
    """Return time as words
    based on relevant condition"""
    if hours == 12:
        hours2 = words_dict.get(1)
    else:
        hours2 = words_dict.get(hours+1)
    if hours == 12 and minutes == 0 and period == 'before midday':
        time_words = 'Midnight'
    elif hours == 12 and minutes == 0 and period == 'after midday':
        time_words = 'Midday'
    elif minutes == 0:
        time_words = "{0} o'clock {1}.".format(str(words_dict.get(hours)).title(),
                                               period)
    elif minutes == 15:
        time_words = "Quarter past {0} {1}.".format(words_dict.get(hours),
                                                    period)
    elif minutes == 30:
        time_words = "Half past {0} {1}.".format(words_dict.get(hours),
                                                 period)
    elif minutes == 45:
        time_words = "Quarter to {0} {1}.".format(hours2,
                                                  period)
    elif minutes < 30:
        min_str = words_dict.get(minutes).capitalize()
        min_num = "" if minutes == 1 else "s"
        time_words = "{0} minute{1} past {2} {3}.".format(min_str,
                                                          min_num,
                                                          words_dict.get(hours),
                                                          period)
    else:
        min_str = words_dict.get(60 - minutes).capitalize()
        min_num = "" if 60 - minutes == 1 else "s"
        time_words = '{0} minute{1} to {2} {3}.'.format(min_str,
                                                        min_num,
                                                        hours2,
                                                        period)
    return time_words


def time_as_words(input_time):
    """Convert 24hr format time
    into time as words"""
    words_dict = words_lookup()
    time_str = validate_time_format(input_time)
    hours, minutes, period = extract_time(time_str)
    time_words = time_conversion(words_dict, hours, minutes, period)
    print(time_words)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Convert 24hr format time into time as words")
    parser.add_argument("-t", "--input_time", metavar="time", type=str, required=True,
                        help='input time in the following format 00:00 to 23:59')
    args = parser.parse_args()
    time_as_words(input_time=args.input_time)

Python模块:TimeAsWords

object session {

  val PeriodLookup = Map(1 -> "before midday", 2 -> "after midday")

  def ExtractTime(InputTime: String, PeriodLookup: Map[Int, String]): (Int, Int, String) = {
    // extract hours from string
    val HrsInt = InputTime.take(2).toInt
    // convert HrsInt into 12hrs using (12 - ((HrsInt) % 12)
    val Hrs12 = 12
    // extract minutes from string
    val MinInt= InputTime.takeRight(2).toInt
    // determine PdString (PeriodLookup(2) if HrsInt >= 12 else PeriodLookup(1))
    val PdString = PeriodLookup(1).mkString
    new Tuple3(HrsInt, MinInt , PdString)
  }
  val (hours1, minutes1, period1) = ExtractTime("18:45", PeriodLookup)
  println(hours1, minutes1, period1)
}

更新版本:Scala对象ExtractTime方法

1 个答案:

答案 0 :(得分:2)

您没有从ExtractTime返回任何内容,但您已将(Int, Int, String)定义为returnType。

因此,您要么将函数定义为

def ExtractTime(InputTime: String, PeriodLookup: Map[Int, String]) : Unit = {

或者您必须在(Int, Int, String)函数的末尾返回ExtractTime

(Hrs12Int, MinInt, PdString)

那应该让你去