除了猜测(就像我在下面所做的那样)之外,是否有更直接、更有效的方法来反思性检索 JavaScript 环境支持的所有货币列表?
function getSupportedCurrencies() {
function $(amount, currency) {
let locale = 'en-US';
let options = {
style: 'currency',
currency: currency,
currencyDisplay: "name"
};
return Intl.NumberFormat(locale, options).format(amount);
}
const getAllPossibleThreeLetterWords = () => {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const arr = [];
let text = '';
for (let i = 0; i < chars.length; i++) {
for (let x = 0; x < chars.length; x++) {
for (let j = 0; j < chars.length; j++) {
text += chars[i];
text += chars[x];
text += chars[j];
arr.push(text);
text = '';
}
}
}
return arr;
};
let ary = getAllPossibleThreeLetterWords();
let currencies = [];
const rx = /(?<= ).+/; // This line doesn't work in Firefox versions older than version 78 due to bug 1225665: https://bugzilla.mozilla.org/show_bug.cgi?id=1225665
ary.forEach((cur) => {
let output = $(0, cur).trim();
if (output.replace(/^[^ ]+ /, '') !== cur) {
let obj = {};
obj.code = cur;
obj.name = output.match(rx)[0];
currencies.push(obj);
}
});
return currencies;
}
console.log(getSupportedCurrencies());
现在,正如公认的答案所提供的那样,详尽的测试可能是这里最合理的实际策略。而且,新货币不会出现,旧货币也不会消亡,而且有特定的频率。任何保持最新的实施所支持的货币几乎总是反映现实。所以尝试看看的方法确实不会失败。
但是从规范方面进一步阐述这一点,规范实际上只关心货币是否“格式良好”:三个 ASCII 字母。如果生成的代码是已知货币,您将获得友好的行为。否则,您将大致优雅地回退到代码本身。因此,有争议不需要公开支持的列表:货币代码对于许多用户来说至少是一个相对容易理解的东西,可能就像在大多数 UI 中看到类似“3 USD”或“5 CAD”的东西,其中价格或成本是暗示通常意味着用户的货币。
在未来,然而,公开一组公认货币的规范提案正在顺利走向标准化。初始实现可能会在 2021 年底之前开始出现在 Web 浏览器的 JS 实现中,让您可以这样做:
// This will return an array of currency codes supported
// by Intl.NumberFormat and Intl.DisplayNames, e.g.:
// ["ADP", "AED", ..., "JPY", ..., "USD", ...]
var currencies = Intl.supportedValuesOf("currency");
console.log(currencies);
您可以通过此 XML 加载已知列表:
https://www.currency-iso.org/dam/downloads/lists/list_one.xml
该列表可以在这里找到:https://www.currency-iso.org/en/home/tables/table-a1.html
<ISO_4217 Pblshd="2018-08-29">
<CcyTbl>
<CcyNtry>
<CtryNm>
UNITED KINGDOM OF GREAT BRITAIN AND NORTHERN IRELAND (THE)
</CtryNm>
<CcyNm>Pound Sterling</CcyNm>
<Ccy>GBP</Ccy>
<CcyNbr>826</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
<CcyNtry>
<CtryNm>UNITED STATES OF AMERICA (THE)</CtryNm>
<CcyNm>US Dollar</CcyNm>
<Ccy>USD</Ccy>
<CcyNbr>840</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
</CcyTbl>
</ISO_4217>
var xmlString = getSampleCurrencyXml();
var xmlData = (new window.DOMParser()).parseFromString(xmlString, "text/xml");
var knownCodes = [].slice.call(xmlData.querySelectorAll('Ccy')).map(n => n.textContent)
// Fetch the XML instead?
fetch('https://www.currency-iso.org/dam/downloads/lists/list_one.xml', { cache: 'default' })
.then(response => response.text())
.then(xmlStr => (new window.DOMParser()).parseFromString(xmlStr, "text/xml"))
.then(data => knownCodes = data); // This may not work in the Stack Snippet
console.log(getSupportedCurrencies().map(c => c.code + '\t' + c.name).join('\n'));
function getSupportedCurrencies() {
function $(amount, currency) {
return Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency,
currencyDisplay: 'name'
}).format(amount);
}
return knownCodes.reduce((currencies, cur) => {
return (output => {
return output.replace(/^[^ ]+ /, '') !== cur ?
currencies.concat({
code: cur,
name: output.match(/(?<= ).+/)[0]
}) :
currencies;
})($(0, cur).trim());
}, []);
}
function getSampleCurrencyXml() {
return `
<ISO_4217 Pblshd="2018-08-29">
<CcyTbl>
<CcyNtry>
<CtryNm>
UNITED KINGDOM OF GREAT BRITAIN AND NORTHERN IRELAND (THE)
</CtryNm>
<CcyNm>Pound Sterling</CcyNm>
<Ccy>GBP</Ccy>
<CcyNbr>826</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
<CcyNtry>
<CtryNm>UNITED STATES OF AMERICA (THE)</CtryNm>
<CcyNm>US Dollar</CcyNm>
<Ccy>USD</Ccy>
<CcyNbr>840</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
</CcyTbl>
</ISO_4217>
`;
}
.as-console-wrapper { top: 0; max-height: 100% !important; }
如果您仍然想生成代码,您可以使用可迭代的乘积。
itertools.product
函数。
let ary = product('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), 3).map(a => a.join(''));
function product(iterables, repeat) {
var argv = Array.prototype.slice.call(arguments), argc = argv.length;
if (argc === 2 && !isNaN(argv[argc - 1])) {
var copies = [];
for (var i = 0; i < argv[argc - 1]; i++) { copies.push(argv[0].slice()); }
argv = copies;
}
return argv.reduce((accumulator, value) => {
var tmp = [];
accumulator.forEach(a0 => value.forEach(a1 => tmp.push(a0.concat(a1))));
return tmp;
}, [[]]);
}
console.log(getSupportedCurrencies().map(c => c.code + '\t' + c.name).join('\n'));
function getSupportedCurrencies() {
function $(amount, currency) {
return Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency,
currencyDisplay: 'name'
}).format(amount);
}
let ary = product('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), 3).map(a => a.join(''));
return ary.reduce((currencies, cur) => {
return (output => {
return output.replace(/^[^ ]+ /, '') !== cur
? currencies.concat({ code : cur, name : output.match(/(?<= ).+/)[0] })
: currencies;
})($(0, cur).trim());
}, []);
}
function product(iterables, repeat) {
var argv = Array.prototype.slice.call(arguments), argc = argv.length;
if (argc === 2 && !isNaN(argv[argc - 1])) {
var copies = [];
for (var i = 0; i < argv[argc - 1]; i++) { copies.push(argv[0].slice()); }
argv = copies;
}
return argv.reduce((accumulator, value) => {
var tmp = [];
accumulator.forEach(a0 => value.forEach(a1 => tmp.push(a0.concat(a1))));
return tmp;
}, [[]]);
}
.as-console-wrapper { top: 0; max-height: 100% !important; }