- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有一个包含混合的 CR
、LF
和 CRLF
换行符的文本。
像这样:“\n\n Lorem\r Ipsum\n 是\r\n 只是\n 打印\r 和排版行业的\n 虚拟\r\n 文本。\n\n”
。
我正在将此文本加载到简单的文本编辑器 (NSTextView
/UITextView
)。视觉换行符看起来一样;只是一个新行。
我可以在简单的文本编辑器中浏览文本、选择文本、剪切、复制、粘贴......
问题:如何从绝对
字符位置获取行
和列
编号(即选择NSRange) ?还有,如何从已知的行
和列
数字中获取绝对
字符位置?
谢谢!
更新 1:
line
和 column
数字 - 简单表示光标位置。line
和 column
编号 - 具有基于One 的编号。绝对
字符位置 - 具有基于零的编号。当前解决方案的示例代码。它从绝对
字符位置计算行
和列
号,反之亦然。但它不会重新计算文本更改的映射。
struct TextString {
struct Cursor {
let line: Int
let column: Int
}
struct Mapping {
let lineNumber: Int
let lineLength: Int
let absolutePosition: Int
fileprivate var absoluteStart: Int {
return absolutePosition - lineLength
}
}
let string: String
private (set) var mappings: [Mapping] = []
init(string: String) {
self.string = string
mappings = setupMappings()
}
}
extension TextString {
func cursor(from position: Int) -> Cursor? {
guard position > 0 else {
return nil
}
guard let mapping = mappings.first(where: { $0.absolutePosition >= position && $0.absoluteStart <= position }) else {
return nil
}
let result = Cursor(line: mapping.lineNumber, column: position - mapping.absoluteStart)
return result
}
func position(from cursor: Cursor) -> Int? {
guard let line = mappings.element(at: cursor.line - 1) else {
return nil
}
guard line.lineLength >= cursor.column else {
return nil
}
let result = line.absoluteStart + cursor.column
return result
}
}
extension TextString {
private func setupMappings() -> [Mapping] {
var mappings: [Mapping] = []
var line = 1
var previousAbsolutePosition = 0
var delta = 0
let scanner = Scanner(string: string)
scanner.charactersToBeSkipped = nil
while !scanner.isAtEnd {
if scanner.scanUpToCharacters(from: .newlines) != nil {
let charactersLocation = scanner.scanLocation - delta
if let newLines = scanner.scanCharacters(from: .newlines) {
for index in 0..<newLines.count {
let absolutePosition = charactersLocation + 1 + index // `+1` is newLine itself
mappings.append(Mapping(lineNumber: line, lineLength: absolutePosition - previousAbsolutePosition,
absolutePosition: absolutePosition))
previousAbsolutePosition = absolutePosition
line += 1
}
delta = scanner.scanLocation - previousAbsolutePosition
} else {
// Only happens when we at last line withot newline.
let absolutePosition = charactersLocation
mappings.append(Mapping(lineNumber: line, lineLength: absolutePosition - previousAbsolutePosition,
absolutePosition: absolutePosition))
line += 1
previousAbsolutePosition = charactersLocation
}
} else if let newLines = scanner.scanCharacters(from: .newlines) { // Text begins with new lines.
for index in 0..<newLines.count {
let absolutePosition = 1 + index // `+1` is newLine itself
mappings.append(Mapping(lineNumber: line, lineLength: absolutePosition - previousAbsolutePosition,
absolutePosition: absolutePosition))
previousAbsolutePosition = absolutePosition
line += 1
}
delta = scanner.scanLocation - previousAbsolutePosition
}
}
assert(previousAbsolutePosition == string.count)
return mappings
}
}
更新 2:RegEx 版本。
private func setupMappingsUsingRegex() throws -> [Mapping] {
if string.isEmpty {
return []
}
var mappings: [Mapping] = []
let regex = try NSRegularExpression(pattern: "(\\r\\n)|(\\n)|(\\r)")
let matches = regex.matches(in: string, range: NSRange(location: 0, length: string.unicodeScalars.count))
var line = 1
var previousAbsolutePosition = 0
var delta = 0
// String without any newline.
if matches.isEmpty {
let mapping = Mapping(lineNumber: 1, lineLength: string.count, absolutePosition: string.count)
mappings.append(mapping)
return mappings
}
for match in matches {
let absolutePosition = match.range.location - delta + 1
let mapping = Mapping(lineNumber: line, lineLength: absolutePosition - previousAbsolutePosition,
absolutePosition: absolutePosition)
mappings.append(mapping)
delta += match.range.length - 1
previousAbsolutePosition = absolutePosition
line += 1
}
// Rest of the string without newline at the end.
if previousAbsolutePosition < string.count {
let mapping = Mapping(lineNumber: line, lineLength: string.count - previousAbsolutePosition,
absolutePosition: string.count)
mappings.append(mapping)
previousAbsolutePosition = string.count
}
assert(previousAbsolutePosition == string.count)
return mappings
}
性能:22400 个字符(200 行)分析 1000 次。
最佳答案
我建议您使用正则表达式分隔字符串。如果您看到 \n
、\r
和 \r\n
,假设您想拆分一个子字符串,则正则表达式类似于
var content: String = <Your text here>
let regex = try! NSRegularExpression(pattern: "(\\n)|(\\r)|(\\r\\n)")
let matchs = regex.matches(in: content, range: NSRange(location: 0, length: content.count)).map{(content as NSString).substring(with: $0.range)}
然后你可以在匹配的结果中循环并获取索引和范围等
关于iOS:字符串。从绝对位置获取行号和列号,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47207611/
猫f1.txt阿曼维沙尔阿杰贾伊维杰拉胡尔曼尼什肖比特批评塔夫林现在输出应该符合上面给定的条件 最佳答案 您可以在文件读取循环中设置一个计数器并打印它, 计数=0 读取行时做 让我们数一数++ if
我正在尝试查找文件 1 和文件 2 中的共同行。如果公共(public)行存在,我想写入文件 2 中的行,否则打印文件 1 中的非公共(public)行。fin1 和 fin2 是这里的文件句柄。它读
我有这个 SQL 脚本: CREATE TABLE `table_1` ( `IDTable_1` int(11) NOT NULL, PRIMARY KEY (`IDTable_1`) );
我有 512 行要插入到数据库中。我想知道提交多个插入内容是否比提交一个大插入内容有任何优势。例如 1x 512 行插入 -- INSERT INTO mydb.mytable (id, phonen
如何从用户中选择user_id,SUB(row, row - 1),其中user_id=@userid我的表用户,id 为 1、3、4、10、11、23...(不是++) --id---------u
我曾尝试四处寻找解决此问题的最佳方法,但我找不到此类问题的任何先前示例。 我正在构建一个基于超本地化的互联网购物中心,该区域分为大约 3000 个区域。每个区域包含大约 300 个项目。它们是相似的项
preg_match('|phpVersion = (.*)\n|',$wampConfFileContents,$result); $phpVersion = str_replace('"','',
我正在尝试创建一个正则表达式,使用“搜索并替换全部”删除 200 个 txt 文件的第一行和最后 10 行 我尝试 (\s*^(\h*\S.*)){10} 删除包含的前 10 行空白,但效果不佳。 最
下面的代码从数据库中获取我需要的信息,但没有打印出所有信息。首先,我知道它从表中获取了所有正确的信息,因为我已经在 sql Developer 中尝试过查询。 public static void m
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我试图在两个表中插入记录,但出现异常。您能帮我解决这个问题吗? 首先我尝试了下面的代码。 await _testRepository.InsertAsync(test); await _xyzRepo
这个基本的 bootstrap CSS 显示 1 行 4 列: Text Text Text
如果我想从表中检索前 10 行,我将使用以下代码: SELECT * FROM Persons LIMIT 10 我想知道的是如何检索前 10 个结果之后的 10 个结果。 如果我在下面执行这段代码,
今天我开始使用 JexcelApi 并遇到了这个:当您尝试从特定位置获取元素时,不是像您通常期望的那样使用sheet.getCell(row,col),而是使用sheet.getCell(col,ro
我正在尝试在我的网站上开发一个用户个人资料系统,其中包含用户之前发布的 3 个帖子。我可以让它选择前 3 条记录,但它只会显示其中一条。我是不是因为凌晨 2 点就想编码而变得愚蠢? query($q)
我在互联网上寻找答案,但找不到任何答案。 (我可能问错了?)我有一个看起来像这样的表: 我一直在使用查询: SELECT title, date, SUM(money) FROM payments W
我有以下查询,我想从数据库中获取 100 个项目,但 host_id 多次出现在 urls 表中,我想每个 host_id 从该表中最多获取 10 个唯一行。 select * from urls j
我的数据库表中有超过 500 行具有特定日期。 查询特定日期的行。 select * from msgtable where cdate='18/07/2012' 这将返回 500 行。 如何逐行查询
我想使用 sed 从某一行开始打印 n 行、跳过 n 行、打印 n 行等,直到文本文件结束。例如在第 4 行声明,打印 5-9,跳过 10-14,打印 15-19 等 来自文件 1 2 3 4 5 6
我目前正在执行验证过程来检查用户的旧密码,但问题是我无法理解为什么我的查询返回零行,而预期它有 1 行。另一件事是,即使我不将密码文本转换为 md5,哈希密码仍然得到正确的答案,但我不知道为什么会发生
我是一名优秀的程序员,十分优秀!