更确切地说,我需要知道是否(以及如果可能,如何)我可以找到给定字符串是否具有双字节字符。基本上,我需要打开一个弹出窗口来显示一个给定的文本,它可以包含双字节字符,如中文或日文。在这种情况下,我们需要调整窗口大小,而不是英文或ASCII。 任何人都有线索?
答案 0 :(得分:34)
我在这个问题上使用了mikesamuel回答。但是我注意到也许是因为这种形式在u
之前只应该有一个转义斜杠,例如\u
而非\\u
使这项工作正常进行。
function containsNonLatinCodepoints(s) {
return /[^\u0000-\u00ff]/.test(s);
}
适合我:)
答案 1 :(得分:27)
JavaScript将文本内部保存为UCS-2,它可以编码相当广泛的Unicode子集。
但这与你的问题没有密切关系。一种解决方案可能是遍历字符串并检查每个位置的字符代码:
function isDoubleByte(str) {
for (var i = 0, n = str.length; i < n; i++) {
if (str.charCodeAt( i ) > 255) { return true; }
}
return false;
}
这可能没有您想要的那么快。
答案 2 :(得分:9)
我已在最佳答案中对这两个函数进行了基准测试,并认为我会分享结果。这是我使用的测试代码:
box.rect
当我跑步时,我得到了:
Texture* box = new Texture;
box->rect
因此对于这个特定的字符串,正则表达式解决方案的速度提高了约3倍。
但请注意,对于第一个字符为unicode的字符串,const text1 = `The Chinese Wikipedia was established along with 12 other Wikipedias in May 2001. 中文維基百科的副標題是「海納百川,有容乃大」,這是中国的清朝政治家林则徐(1785年-1850年)於1839年為`;
const regex = /[^\u0000-\u00ff]/; // Small performance gain from pre-compiling the regex
function containsNonLatinCodepoints(s) {
return regex.test(s);
}
function isDoubleByte(str) {
for (var i = 0, n = str.length; i < n; i++) {
if (str.charCodeAt( i ) > 255) { return true; }
}
return false;
}
function benchmark(fn, str) {
let startTime = new Date();
for (let i = 0; i < 10000000; i++) {
fn(str);
}
let endTime = new Date();
return endTime.getTime() - startTime.getTime();
}
console.info('isDoubleByte => ' + benchmark(isDoubleByte, text1));
console.info('containsNonLatinCodepoints => ' + benchmark(containsNonLatinCodepoints, text1));
会立即返回,因此比正则表达式(仍然具有正则表达式的开销)快得多。
例如对于字符串isDoubleByte => 2421
containsNonLatinCodepoints => 868
,我得到了这些结果:
isDoubleByte()
为了充分利用两者,最好将两者结合起来:
中国
在这种情况下,如果第一个字符是中文(很可能整个文本是中文),该功能将很快并立即返回。如果没有,它将运行正则表达式,这仍然比单独检查每个字符更快。
答案 3 :(得分:6)
实际上,所有字符都是Unicode,至少从Javascript引擎的角度来看。
不幸的是,仅仅存在特定Unicode范围内的字符将不足以确定您需要更多空间。有许多字符占用的空间大致与其他具有远远高于ASCII范围的Unicode代码点的字符相同。印刷引号,带变音符号的字符,某些标点符号和各种货币符号都在低ASCII范围之外,并且在Unicode基本多语言平面上的相当不同的位置分配。
通常,我参与过的项目选择为所有语言提供额外的空间,或者有时使用javascript来确定具有自动滚动条css属性的窗口是否实际上具有高度会触发滚动条的内容。
如果检测到CJK字符的存在或计数足以确定您需要一些额外空间,则可以使用以下范围构造正则表达式: [\ u3300 \ u9fff \ uf900- \ ufaff],并使用它来提取匹配的字符数。 (这有点过于粗糙,并且错过了所有非BMP案例,可能会排除其他一些相关范围,并且很可能包括一些不相关的字符,但这是一个起点)。
同样,你只能在没有全文渲染引擎的情况下管理粗略启发式,因为你真正想要的是像GDI的MeasureString(或任何其他文本渲染引擎的等价物)。我已经有一段时间了,但我认为最接近的HTML / DOM等价物是在div上设置宽度并请求高度(剪切和粘贴重用,如果这包含错误,请道歉):
o = document.getElementById("test");
document.defaultView.getComputedStyle(o,"").getPropertyValue("height"))
答案 4 :(得分:2)
这是基准测试:http://jsben.ch/NKjKd
这快得多:
function containsNonLatinCodepoints(s) {
return /[^\u0000-\u00ff]/.test(s);
}
比这个:
function isDoubleByte(str) {
for (var i = 0, n = str.length; i < n; i++) {
if (str.charCodeAt( i ) > 255) { return true; }
}
return false;
}
答案 5 :(得分:0)
为什么不让窗口根据运行时高度/宽度自行调整大小?
在弹出窗口中运行类似的内容:
window.resizeTo(document.body.clientWidth, document.body.clientHeight);