在保持浮动值的同时翻转javascript对象中的键和值

时间:2019-05-02 20:32:35

标签: javascript json object

我有一个JavaScript对象,该对象具有一天中的时间以及该时间的浮动表示形式。我不小心将它们以错误的顺序放置,因此我迅速翻转了它们,但现在浮子为弦。

这是该对象的较短版本(在翻转之前):

const conversion_chart = {
1:'12:00 AM',
0.04: '1:00 AM',
0.08: '2:00 AM',
0.13: '3:00 AM',
0.17: '4:00 AM',
0.21: '5:00 AM',
0.25: '6:00 AM',
0.29: '7:00 AM',
0.33: '8:00 AM',
0.38: '9:00 AM',
0.42: '10:00 AM',
0.46: '11:00 AM',
0.5: '12:00 PM',
}

现在具有此功能:

function flip(o){
  var ret = {};
  for(var key in o){
     ret[o[key]] = key;
  }
  return ret;
}

console.log(flip(conversion_chart));

它返回:

'12:00 AM': '1',
'1:00 AM': '0.04',
'2:00 AM': '0.08',
'3:00 AM': '0.13',
'4:00 AM': '0.17',
'5:00 AM': '0.21',
'6:00 AM': '0.25',
'7:00 AM': '0.29',
'8:00 AM': '0.33',
'9:00 AM': '0.38',
'10:00 AM': '0.42',
'11:00 AM': '0.46',
'12:00 PM': '0.5'

除了现在新的值(即:1, 0.04, 0.08等仍然是浮点数)以外,我基本上打算这样做。

如何使新值成为浮点数?

感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

您可以使用parseFloat

function flip(o){
  var ret = {};
  for(var key in o){
     ret[o[key]] = parseFloat(key);
  }
  return ret;
}

glTexImage2D

答案 1 :(得分:0)

一种可能的解决方案是使用Unary Plus运算符,MDN说:

  

一元加是将某物转换为数字的最快且首选的方式,因为它不会对该数字执行任何其他操作。

无论如何,如果我们谈论对象keys,则应注意对象numbers始终是字符串,而不是type

const conversion_chart = {
  1: '12:00 AM',
  0.04: '1:00 AM',
  0.08: '2:00 AM',
  0.13: '3:00 AM',
  0.17: '4:00 AM',
  0.21: '5:00 AM',
  0.25: '6:00 AM',
  0.29: '7:00 AM',
  0.33: '8:00 AM',
  0.38: '9:00 AM',
  0.42: '10:00 AM',
  0.46: '11:00 AM',
  0.5: '12:00 PM',
}

function flip(o)
{
  var ret = {};

  for (var key in o)
  {
    ret[o[key]] = +key;
  }

  return ret;
}

console.log(flip(conversion_chart));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

或者,您也可以在Array.reduce()上使用Object.entries()

const conversion_chart = {
  1: '12:00 AM',
  0.04: '1:00 AM',
  0.08: '2:00 AM',
  0.13: '3:00 AM',
  0.17: '4:00 AM',
  0.21: '5:00 AM',
  0.25: '6:00 AM',
  0.29: '7:00 AM',
  0.33: '8:00 AM',
  0.38: '9:00 AM',
  0.42: '10:00 AM',
  0.46: '11:00 AM',
  0.5: '12:00 PM',
}

const flip = (o) => Object.entries(o).reduce(
    (acc, [k, v]) => ({...acc , [v]: +k}),
    {}
);

console.log(flip(conversion_chart));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

答案 2 :(得分:0)

在查看您的问题时,您似乎想将12小时制表示法中指定的时间转换为小数部分。使用查找表来完成此操作很快就会导致一个巨大的表,并且很容易出错。

解决问题的另一种方法是改为计算值。使用这种方法,它可以在一天中处理所有1440分钟的时间,而无需查找表。

下面有两个函数:time12hToDayfraction可以将12个小时的时钟转换为一天的时间,dayFractionToTime12h可以将一个天的时钟转换为12小时的时间。

对代码进行了大量注释,以帮助您了解其功能。如果删除所有注释,您将看到代码相当紧凑。

function time12hToDayfraction(input) {
  if ( typeof input !== 'string') throw TypeError('Invalid type. Expexted string');
  // Using regex validate a valid time and to split it into hours, minutes and AM/PM
  // ^                Match start of string
  // (1[0-2]|[0-9])   Match 1 follwed by a 0,1 or 2, or 0,1,2,3,4,5,6,7,8 or 9
  // :                Match the colon
  // ([0-5][0-9])     Match 0,1,2,3,4 or 5 followed by 0,1,2,3,4,5,6,7,8 or 9.
  // ([AP]M)          Match A or P followed by M
  // $                Match end of string
  // toUpperCase converts the string to upper case. I could have made the regex
  // case insensitive, but when calculating the hours below I need to know if
  // if was AM or PM, and now I can make a simple string comparison instead of
  // a case insensitive comparison.
  const parts = input.toUpperCase().match(/^(1[0-2]|[0-9]):([0-5][0-9]) ([AP]M)$/);
  if (!parts) throw Error('Invalid format');

  // Convert string in parts to numbers
  const value = {
    // parts[1] is the hours.
    // parts[2] is the minutes
    // parts[3] is "AM" or "PM"
    // Using reminder % to make 12 = 0.
    // Using conditional (ternary) operator to decide if 0 or 12 should be added.
    hours : ( +parts[1] % 12 ) + ( parts[3] === 'PM' ? 12 : 0 ), // Convert to 24 hours
    minutes : +parts[2]
  }
  // This returns MIDNIGHT (12:00 AM) as 0, and NOON (12:00 PM) as 0.5
  return ( value.hours + ( value.minutes / 60 ) ) / 24
  // I saw that you example had "12:00 AM" as 1. If you want "12:00 AM" as 1,
  // and "12:01 AM" as slmost zero, replace the line above with:
  // return (( value.hours + ( value.minutes / 60 ) ) / 24) || 1
}

// Converts a day fraction to time 12 h
function dayFractionToTime12h(input) {
  if ( typeof input !== 'number') throw TypeError('Invalid type. Expexted number');
  if ( input < 0 || input > 1 ) throw RangeError('Input shuld be 0 - 1');
  const clock24 = input * 24; // Convert input to 24 hour clock.
  const value = {
    // Convert 24-hour-clock to 12-hour-clock by using
    // reminder % 12 to get a value between 0-11 and locical or-operator
    // to convert 0 to 12.
    hours : (Math.floor( clock24 ) % 12) || 12,
    // Calculate minutes
    minutes : Math.round(clock24 * 60) % 60,
    apm : clock24 < 12 ? 'AM' : 'PM'
  }
  return `${value.hours}:${value.minutes.toString().padStart(2,'0')} ${value.apm}`;
}


// Example
[
  '12:00 AM', '12:30 AM', '1:00 AM', '2:00 AM', '3:00 AM', '4:00 AM', '5:00 AM',
  '6:00 AM', '7:00 AM', '8:00 AM', '9:00 AM', '10:00 AM', '11:00 AM',
  '12:00 PM', '1:00 PM', '2:00 PM', '3:00 PM', '4:00 PM', '5:00 PM',
  '6:00 PM', '7:00 PM', '8:00 PM', '9:00 PM', '10:00 PM', '11:00 PM',
  '11:59 PM'
].forEach( input => {
  const frac = time12hToDayfraction(input);
  const time = dayFractionToTime12h(frac);
  if (input != time) throw Error(`input!=time "${input}" "${time}"`);
  console.log( input, frac.toFixed(2), time );
});