Переключение ключей и значений в объекте javascript с сохранением значений с плавающей запятой - PullRequest
0 голосов
/ 02 мая 2019

У меня есть объект 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 ]

2 голосов
/ 02 мая 2019

Вы можете использовать parseFloat:

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

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat

0 голосов
/ 04 мая 2019

При взгляде на ваш вопрос выглядело, как будто вы пытаетесь преобразовать время, указанное в 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 );
});
0 голосов
/ 02 мая 2019

Одним из возможных решений является использование оператора Unary Plus , MDN говорит:

unary plus - самый быстрый и предпочтительный способ преобразования чего-либов число, потому что он не выполняет никаких других операций над числом.

В любом случае, вы должны заметить, что объект 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;}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...