是否可以 return 比较值+来自三元运算的字符串而不重复所述值?
Is it possible to return compared value + a string from a ternary operation without repeating said value?
我正在尝试找到更简单的问题解决方案。
问题:
我想尝试并简化它,但我不知道从哪里开始。
let days = Math.floor(distance / (1000 * 60 * 60 * 24));
if(days > 0) {
days = days + "d";
}
尝试:
我在想我可以使用三元运算符来 return 计算 + "d" 像这样:
let days = Math.floor(distance / (1000 * 60 * 60 * 24)) === 0 ? Math.floor(distance / (1000 * 60 * 60 * 24)) + "d" : "";
然而,在我看来这非常混乱,我想不出其他方法。
当前结构
我目前正在为这样的计时器计算天数、小时数、分钟数和秒数:
let distance = expiry - now;
let days = Math.floor(distance / (1000 * 60 * 60 * 24));
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
之后,如果是 greater than 0
,我只想显示天;如果是 greater than 0
,我只想显示分钟,依此类推。我目前正在使用一堆 if 语句和一个布尔值来检查是否已经找到大于 0 的值。像这样:
let isSet = false;
if (days > 0 && !isSet) {
current = days + "d";
isSet = true;
}
if (hours > 0 && !isSet) {
current = hours + "h";
isSet = true;
}
if (minutes > 0 && !isSet) {
current = minutes + "m";
isSet = true;
}
if (seconds > 0 && !isSet) {
current = seconds + "s";
isSet = true;
}
if (seconds < 0 && !isSet) {
current = "expired";
isSet = true;
}
然而,这确实感觉非常重复和错误(即使它有效)。
您可以使用
const now = new Date(2018, 1, 5, 10, 11);
const expiry = new Date(2018, 2, 5, 5, 6);
let distance = expiry - now;
let days = Math.floor(distance / (1000 * 60 * 60 * 24));
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
const arr = [
...(days > 0 ? [days + "d"] : []),
...(hours > 0 ? [hours + "h"] : []),
...(minutes > 0 ? [minutes + "m"] : []),
...(seconds > 0 ? [seconds + "s"] : []),
];
const current = arr.length ? arr.join(' ') : "expired";
console.log(current);
您可以将信息存储为对象的属性,而不是将信息存储为变量。然后您可以遍历每个 属性 并设置您想要的文本。
const dateInfo = {
days: 1E3 * 60 * 60 * 24,
hours: 1E3 * 60 * 60,
minutes: 1E3 * 60,
seconds: 1E3
};
function check(distance) {
return Object.keys(dateInfo).reduce(function(result, key) {
result[key] = Math.floor(distance / dateInfo[key]);
distance -= dateInfo[key] * result[key];
result[key] = result[key] > 0 ? `${result[key]}${key}` : "";
return result;
}, {});
}
let result = check(1E9);
console.log(result); // result
console.log(Object.values(result).join(" ")); // Print all properties
console.log(Object.values(result).find(item => item) || "Expired"); // Print first property
最高效紧凑的方式是:
const dateInfo = {
d: 1E3 * 60 * 60 * 24,
h: 1E3 * 60 * 60,
m: 1E3 * 60,
s: 1E3
};
function check(distance) {
// Find the biggest proprty that is still smaller than the total difference
var key = Object.keys(dateInfo).find(key => dateInfo[key] <= distance);
// No need for % since distance > dateInfo[key]
return `${Math.floor(distance / dateInfo[key]) || "expired"}${key || ""}`;
}
console.log(check(3E9)); //34d
console.log(check(3E7)); //8h
console.log(check(3E5)); //5m
console.log(check(3E3)); //3s
console.log(check(3E0)); //expired
您最大的问题是 isSet
变量,而不是您使用的是 if
语句。
您应该 使用 else
:
而不是设置 isSet
var current;
if (days > 0) {
current = days + "d";
} else if (hours > 0) {
current = hours + "h";
} else if (minutes > 0) {
current = minutes + "m";
} else if (seconds > 0) {
current = seconds + "s";
} else if (seconds < 0) {
current = "expired";
} // else seconds == 0
您可能想在此处使用条件运算符。您不应该尝试将它们合并到 days = Math.floor(distance / (1000 * 60 * 60 * 24))
计算中,保持原样 - days
只是一个临时变量。将条件的结果存储在不同的变量 (current
) 中,而不是 days
:
const distance = expiry - now;
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
const current =
(days > 0) ? days + "d" :
(hours > 0) ? hours + "h" :
(minutes > 0) ? minutes + "m" :
(seconds > 0) ? seconds + "s" :
//(seconds == 0) ? undefined :
"expired";
getDurationDetails:function(duration){
var result = [];
var units = {
Year:31536000,
Month:2592000,
Week:604800,
Day: 86400,
Hour: 3600,
Minute: 60,
Second:1,
};
for(var name in units) {
var res = Math.floor(duration/units[name]);
if(res == 1) result.push(" " + res + " " + name);
if(res >= 2) result.push(" " + res + " " + name + "s");
duration %= units[name];
}
return result;
},
试试这个
我认为这种模式的最佳解决方案是在数组中定义范围,然后与它进行比较,以避免代码重复。
var ranges = [
[86400000, 'd'],
[3600000, 'h'],
[60000, 'm'],
[1000, 's'],
]
然后遍历这个数组并检查提供的值是否大于当前周期。
function humanDiff(milliseconds) {
for (var i = 0; i < ranges.length; i++) {
if (milliseconds >= ranges[i][0]) {
return Math.round((milliseconds / ranges[i][0])) + ranges[i][1]
};
}
return milliseconds;
}
示例:
var expiry = new Date('2019-03-26 08:29');
var now = new Date('2019-03-26 05:00');
humanDiff(expiry - now) // 3h
优点:
- 避免不必要的计算(不计算小时和分钟的天数)
- 避免代码重复
- 将设置与执行分开(添加更多指标就像在范围数组中添加新记录一样简单)
您可以获取值的数组,如果找到索引,则将此索引作为值和后缀的访问器,或者将 'expired'
作为值。
let distance = expiry - now,
factors = [86400000, 3600000, 60000, 1000],
values = factors.map(f => [Math.floor(distance / f), distance %= f][0]),
index = values.findIndex(v => v > 0),
result = index === -1 ? 'expired' : value[index] + 'DHMS'[index];
console.log(result);
像您这样的瀑布方法是个不错的主意。当您添加到字符串时,我会修改它以更新距离变量,例如(例如 4d 3h 17m 1s
):
function formatDuration (seconds) {
let s = seconds, r = '', t;
if (s % 86400 !== s) updateR('d', 86400);
if (s % 3600 !== s) updateR('h', 3600);
if (s % 60 !== s) updateR('m', 60);
if (s > 0) updateR('s', 1);
function updateR(unit, n) {
t = Math.floor(s / n);
s %= n;
r += (r === '' ? '' : ' ') + t + unit;
}
return r.replace(/,\s(?=\d{1,2}\s\w+$)/, ' and ') || 'expired';
}
以及更具表现力的版本(例如 4 days, 3 hours, 17 minutes, and 1 second
):
function formatDuration (seconds) {
let s = seconds, r = '', t;
// if (s % 31536000 !== s) updateR(' year', 31536000);
if (s % 86400 !== s) updateR(' day', 86400);
if (s % 3600 !== s) updateR(' hour', 3600);
if (s % 60 !== s) updateR(' minute', 60);
if (s > 0) updateR(' second', 1);
function updateR(unit, n) {
t = Math.floor(s / n);
s %= n;
r += (r === '' ? '' : ', ') + t + unit + (t === 1 ? '' : 's');
}
return r.replace(/,\s(?=\d{1,2}\s\w+$)/, ' and ') || 'expired';
}
我正在尝试找到更简单的问题解决方案。
问题:
我想尝试并简化它,但我不知道从哪里开始。
let days = Math.floor(distance / (1000 * 60 * 60 * 24));
if(days > 0) {
days = days + "d";
}
尝试:
我在想我可以使用三元运算符来 return 计算 + "d" 像这样:
let days = Math.floor(distance / (1000 * 60 * 60 * 24)) === 0 ? Math.floor(distance / (1000 * 60 * 60 * 24)) + "d" : "";
然而,在我看来这非常混乱,我想不出其他方法。
当前结构
我目前正在为这样的计时器计算天数、小时数、分钟数和秒数:
let distance = expiry - now;
let days = Math.floor(distance / (1000 * 60 * 60 * 24));
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
之后,如果是 greater than 0
,我只想显示天;如果是 greater than 0
,我只想显示分钟,依此类推。我目前正在使用一堆 if 语句和一个布尔值来检查是否已经找到大于 0 的值。像这样:
let isSet = false;
if (days > 0 && !isSet) {
current = days + "d";
isSet = true;
}
if (hours > 0 && !isSet) {
current = hours + "h";
isSet = true;
}
if (minutes > 0 && !isSet) {
current = minutes + "m";
isSet = true;
}
if (seconds > 0 && !isSet) {
current = seconds + "s";
isSet = true;
}
if (seconds < 0 && !isSet) {
current = "expired";
isSet = true;
}
然而,这确实感觉非常重复和错误(即使它有效)。
您可以使用
const now = new Date(2018, 1, 5, 10, 11);
const expiry = new Date(2018, 2, 5, 5, 6);
let distance = expiry - now;
let days = Math.floor(distance / (1000 * 60 * 60 * 24));
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
const arr = [
...(days > 0 ? [days + "d"] : []),
...(hours > 0 ? [hours + "h"] : []),
...(minutes > 0 ? [minutes + "m"] : []),
...(seconds > 0 ? [seconds + "s"] : []),
];
const current = arr.length ? arr.join(' ') : "expired";
console.log(current);
您可以将信息存储为对象的属性,而不是将信息存储为变量。然后您可以遍历每个 属性 并设置您想要的文本。
const dateInfo = {
days: 1E3 * 60 * 60 * 24,
hours: 1E3 * 60 * 60,
minutes: 1E3 * 60,
seconds: 1E3
};
function check(distance) {
return Object.keys(dateInfo).reduce(function(result, key) {
result[key] = Math.floor(distance / dateInfo[key]);
distance -= dateInfo[key] * result[key];
result[key] = result[key] > 0 ? `${result[key]}${key}` : "";
return result;
}, {});
}
let result = check(1E9);
console.log(result); // result
console.log(Object.values(result).join(" ")); // Print all properties
console.log(Object.values(result).find(item => item) || "Expired"); // Print first property
最高效紧凑的方式是:
const dateInfo = {
d: 1E3 * 60 * 60 * 24,
h: 1E3 * 60 * 60,
m: 1E3 * 60,
s: 1E3
};
function check(distance) {
// Find the biggest proprty that is still smaller than the total difference
var key = Object.keys(dateInfo).find(key => dateInfo[key] <= distance);
// No need for % since distance > dateInfo[key]
return `${Math.floor(distance / dateInfo[key]) || "expired"}${key || ""}`;
}
console.log(check(3E9)); //34d
console.log(check(3E7)); //8h
console.log(check(3E5)); //5m
console.log(check(3E3)); //3s
console.log(check(3E0)); //expired
您最大的问题是 isSet
变量,而不是您使用的是 if
语句。
您应该 使用 else
:
isSet
var current;
if (days > 0) {
current = days + "d";
} else if (hours > 0) {
current = hours + "h";
} else if (minutes > 0) {
current = minutes + "m";
} else if (seconds > 0) {
current = seconds + "s";
} else if (seconds < 0) {
current = "expired";
} // else seconds == 0
您可能想在此处使用条件运算符。您不应该尝试将它们合并到 days = Math.floor(distance / (1000 * 60 * 60 * 24))
计算中,保持原样 - days
只是一个临时变量。将条件的结果存储在不同的变量 (current
) 中,而不是 days
:
const distance = expiry - now;
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
const current =
(days > 0) ? days + "d" :
(hours > 0) ? hours + "h" :
(minutes > 0) ? minutes + "m" :
(seconds > 0) ? seconds + "s" :
//(seconds == 0) ? undefined :
"expired";
getDurationDetails:function(duration){
var result = [];
var units = {
Year:31536000,
Month:2592000,
Week:604800,
Day: 86400,
Hour: 3600,
Minute: 60,
Second:1,
};
for(var name in units) {
var res = Math.floor(duration/units[name]);
if(res == 1) result.push(" " + res + " " + name);
if(res >= 2) result.push(" " + res + " " + name + "s");
duration %= units[name];
}
return result;
},
试试这个
我认为这种模式的最佳解决方案是在数组中定义范围,然后与它进行比较,以避免代码重复。
var ranges = [
[86400000, 'd'],
[3600000, 'h'],
[60000, 'm'],
[1000, 's'],
]
然后遍历这个数组并检查提供的值是否大于当前周期。
function humanDiff(milliseconds) {
for (var i = 0; i < ranges.length; i++) {
if (milliseconds >= ranges[i][0]) {
return Math.round((milliseconds / ranges[i][0])) + ranges[i][1]
};
}
return milliseconds;
}
示例:
var expiry = new Date('2019-03-26 08:29');
var now = new Date('2019-03-26 05:00');
humanDiff(expiry - now) // 3h
优点:
- 避免不必要的计算(不计算小时和分钟的天数)
- 避免代码重复
- 将设置与执行分开(添加更多指标就像在范围数组中添加新记录一样简单)
您可以获取值的数组,如果找到索引,则将此索引作为值和后缀的访问器,或者将 'expired'
作为值。
let distance = expiry - now,
factors = [86400000, 3600000, 60000, 1000],
values = factors.map(f => [Math.floor(distance / f), distance %= f][0]),
index = values.findIndex(v => v > 0),
result = index === -1 ? 'expired' : value[index] + 'DHMS'[index];
console.log(result);
像您这样的瀑布方法是个不错的主意。当您添加到字符串时,我会修改它以更新距离变量,例如(例如 4d 3h 17m 1s
):
function formatDuration (seconds) {
let s = seconds, r = '', t;
if (s % 86400 !== s) updateR('d', 86400);
if (s % 3600 !== s) updateR('h', 3600);
if (s % 60 !== s) updateR('m', 60);
if (s > 0) updateR('s', 1);
function updateR(unit, n) {
t = Math.floor(s / n);
s %= n;
r += (r === '' ? '' : ' ') + t + unit;
}
return r.replace(/,\s(?=\d{1,2}\s\w+$)/, ' and ') || 'expired';
}
以及更具表现力的版本(例如 4 days, 3 hours, 17 minutes, and 1 second
):
function formatDuration (seconds) {
let s = seconds, r = '', t;
// if (s % 31536000 !== s) updateR(' year', 31536000);
if (s % 86400 !== s) updateR(' day', 86400);
if (s % 3600 !== s) updateR(' hour', 3600);
if (s % 60 !== s) updateR(' minute', 60);
if (s > 0) updateR(' second', 1);
function updateR(unit, n) {
t = Math.floor(s / n);
s %= n;
r += (r === '' ? '' : ', ') + t + unit + (t === 1 ? '' : 's');
}
return r.replace(/,\s(?=\d{1,2}\s\w+$)/, ' and ') || 'expired';
}