“字符串”是一个字符序列。
考虑到您是一名程序员(为什么还要读这篇专门针对程序员的文章?),您很有可能已经知道此定义。 而且我认为,可以假设您已经在至少一种编程语言中使用了“字符串”。
尽管如此,我还要提醒您一次,编程世界中的“弦乐”与“弦乐理论”没有关系 , 谢尔顿·库珀的“弦乐理论”比任何物理学家曾经或可能做的都普及得多。
在本文中,我将向您介绍一些与String相关的非常重要的概念/术语,您可能需要在日常编程中使用它们。 另外,熟悉这些术语可能会在一天的工作面试中对您有所帮助,谁知道呢?
尽管从“语言”方面来看,某些术语的含义有些复杂,但我将尽量避免使用它们,并从程序员需要理解的角度进行解释。 需要提到的另一件事是,我不会显示任何代码示例,也不会显示如何使用自己喜欢的语言进行字符串操作。 我将只讨论这些术语和概念,而您的工作是找出在需要时如何使用它们。 说得通? 好了,走吧。
字符串的主要组成部分是'字符',等等,您已经知道了。 但是您知道字符基本上只是代码表示吗? 我的意思是,计算机不知道字符,字母等,也不将其存储在内存中。 计算机将它们存储为数字(准确地说是二进制)。 有一些约定定义哪个数字代表哪个字符。 该字符集基本上将一些数字或代码点映射到文本字符。 然后,在进行视觉表示时,计算机从内存中读取它们,并根据该映射将它们表示为字符。 这种映射和字符表示就是所谓的“字符编码”。 下一篇文章很好地解释了有关它的一切。 因此,建议您阅读该书,以更好地理解“字符编码”。
大多数新手程序员(尤其是使用类C语言开始编程的程序员)都以为世界上所有字符都是单字节,显然是ASCII字符。 我不会怪他们,因为我也曾经是其中之一。 但是现在我知道这是不对的,并且存在大量的Unicode字符,而且作为程序员,您需要非常频繁地处理它们。 所以,您需要记住的第一件事,
世界上所有字符的创建均不相同,并且它们始终不是单字节字符。
大多数Unicode字符可以存储为16位或2字节数据类型。 但是,仍然有些不能。 Unicode定义了136,000多个代码点 ,其中2个字节可以存储多达65,536个字符。 因此,需要多字节数据类型来存储余数。 因此,您应该记住:
让我们为您提供其他一些信息。
字符编码可以是固定长度或可变长度。 您可能已经听说过UTF-8,UTF-16,UTF-32等编码方案。虽然还有其他多种编码,但是让我们对这三种Unicode字符编码有一个简单的了解。
当您进行国际化和本地化工作时,您对字符编码的知识可能会派上用场。 另外,您可以从单个讨论线程中猜测,该知识在其他一些方面非常重要,例如基于编码,您的文本将消耗多少空间,内存。
我的意思是,在处理String或Text时,请小心字符编码。
大多数语言都提供“字符串”作为基本数据类型。 关于您使用的语言,您需要了解的是,语言的String数据类型是Mutable还是Immutable 。 例如,Java和Python字符串类型是不可变的。 如果您尝试将不可变的String视为可变的,则会抛出错误,并且您可能会想知道:
您可能想知道为什么某些语言中的字符串是不可变的,对吧? 让我们来探讨一下。 您会看到,在像C这样的语言中,它们将字符串存储为字符数组,并且行为类似于通用数组。 因此,由于您可以轻松更改数组,因此也可以更改String。 另一方面,诸如Java和Python之类的语言将字符串视为对象,它们留出了一个特殊的存储区域,称为“字符串常量池”。 当编译器看到String文字时,它将在池中查找String。 如果找到匹配项,则对新文字的引用将指向现有的String,并且不会创建新的String对象。 现有的String仅具有一个参考。 这是使String对象不可变的要点:
在字符串常量池中,一个字符串对象可能具有一个或多个引用。 如果多个引用指向同一String甚至不知道它,那么如果其中一个引用修改了该String值,那就不好了。 这就是为什么String对象是不可变的。
因此,从这里可以学到的是,在使用它们之前,请先确定自己喜欢的语言中字符串的不可变性。
女士们,先生们,是时候学习一些术语了。
字符串S的子字符串是出现在S中的字符串。
让我们说得更清楚些。 字符串的任何顺序部分都是它的子字符串。 因此,“ is nice”是字符串“ This is nice”的子字符串。 但是,“ nice is”不是,因为在字符串“ This is nice”中找不到“ nice is”。 您必须在字符串中找到子字符串。
字符串“ apple ”的所有子字符串的列表为:
“ 苹果 ”,“ 应用 ”,“ pple ”,“ 应用 ”,“ ppl ”,“ ple ”,“ ap ”,“ pp ”,“ pl ”,“ le ”,“ a ”,“ p ”,“ l” ”,“ e ”,“”。
字符串S的前缀是出现在S 开头的S的子字符串。
从一个例子中可以清楚地看出这一点。 字符串“ apple ”的所有前缀的列表为:
“ 苹果 ”,“ 应用 ”,“ 应用 ”,“ ap ”,“ a”
因此,作为前缀,需要从该字符串的开头开始一个子字符串。
字符串的正确前缀不等于字符串本身。 因此,“ apple”将不是“ apple”的适当前缀。
字符串S的后缀是出现在S 末尾的S的子字符串。
字符串“ apple ”的所有子字符串的列表为:
“ 苹果 ”,“ pple ”,“ ple ”,“ le ”,“ e ”
因此,作为后缀,子字符串需要在该字符串的末尾结束。
字符串的适当后缀不等于字符串本身。 因此,“苹果”不会是“苹果”的适当后缀。
子序列的正式定义是:
“ 子 序列是一个序列,可以通过删除一些元素或不删除某些元素而无需更改其余元素的顺序来从另一个序列中得出。”
让我用简单的话解释一下。 字符串是一个字符序列,对吗? 因此,如果我们选择一些字符来保持原始字符串中出现的顺序相同,则结果字符串将是原始字符串的子序列。 假设我们有一个字符串“ Hello”。 然后,“ eo”是该字符串的子序列。 但是“ ol”不会是一个子序列,因为它不在“ Hello”中以相同的顺序出现。
“ 苹果 ”一词的所有子序列表如下:
“ e,l,le,p,pe,pl,ple,p,pe,pl,ple,pp,ppe,ppl,pple,a,ae,al,ale,ap,猿,apl,aple,ap,ap,猿,apl,aple,app,appe,appl,apple ”。
杜德(Dude),您了解到“子字符串”和“子序列”之间的区别吗?
让我们学习一些关于字符串的常见操作。
这意味着将两个或多个字符串连接在一起。
假设有两个字符串: 'Hello'和'World' 。 这两个字符串的串联结果导致另一个字符串“ Hello World” 。
这意味着将字符串的所有字符转换为相同的大小写,即“ LowerCase”或“ UpperCase”。
大写有各种用例。 其中之一是:
如果需要以不区分大小写的方式在两个字符串之间进行比较,则始终需要将两个文本都标准化为“ LowerCase”或“ UpperCase”。
好吧,老实说,它并不总是那么简单。 如果您的字符串包含非拉丁字符,您将遇到一些奇怪的情况。 假设您的字符串是“résumé”,要将字符串转换为UpperCase,通常会将[az]字符集转换为[AZ]字符集。那么, é的UpperCase是什么?在这种情况下,您需要其他一些注意事项,例如Unicode Normalization等,请在此处了解有关此内容的更多信息。
尽管从名称上似乎“加入”类似于“串联”,但是它们之间存在细微但重要的区别。 与“连接”不同,“连接”使用每个字符串元素之间的给定“分隔符”或“胶水”来连接字符串。 因此,如果给出的字符串列表像: ['Hello','world','again']以及分隔符/胶水'-' ,则结果字符串将是: 'Hello-world-again' 。 在某些情况下,分隔符可以是一个空的string(''),其行为与“连接”完全相同。
对字符串进行拆分或标记化意味着根据一个定界符或一组定界符将单个字符串分解为几个部分。 假设您有一个字符串: “为什么这么认真?” 现在,如果您基于空格对这个字符串进行标记化,您将得到一个字符串或标记的列表: ['Why','so','serious?'] 。
注意,定界符不会包含在结果字符串中。
同样,在某些情况下,您可能需要基于模式而不是某些特定的定界符来标记字符串。 这可以通过Regex轻松完成。
修剪/剥离字符串通常意味着从字符串中删除前导和尾随空格。 在此上下文中,空白是所有空白字符(空格,制表符,不间断空格等)和所有行终止符(LF,CR等) 。 因此,给定的字符串:“这很简单”将在修剪/剥离后为“这很简单”。 修剪/剥离的变体包括:
有时您需要为字符串列表定义顺序。 最受欢迎的顺序是“字典顺序” ,也称为“字母顺序”或“字典顺序”。 您已经了解了字典中单词的排序方式,对吗? 这就是字典顺序。 因此,如果按字典顺序对单词['ant','Zebra','apple','applecart']的列表进行排序,则将是:
Zebra
ant
apple
applecart
请注意,按照词典顺序,大写字母排在小写字母之前,这就是为什么“斑马”排在“蚂蚁”之前的原因。 同样,较长的字符串位于相同的前缀较小的字符串之后,这就是“ apple”在“ applecart”之前的原因。
您经常会执行许多与某种字符串搜索和/或比较直接或间接相关的任务。
让我们谈谈一些常见的字符串/模式匹配类型。
其中最常见的是检查两个字符串之间的精确匹配。 您可以合理地假设==运算符可以做到。 但是我想给您一个简单的提示,它可以帮助您节省很多麻烦。 如果将两个字符串存储在两个变量中,并尝试通过==运算符检查它们的相等性,则需要确保您的编程语言是在进行值匹配还是只是引用匹配? 如果您的编程语言将String作为Object对待,那么很可能在您尝试通过==运算符检查两个String Object时, 它将检查两个Object的引用是否相等,而不是其值是否相等 。 另一方面,其他编程语言可能只是检查这两个字符串变量的值相等性。 所以记住这一点。
您在Google搜索或手机联系人搜索中看到过“自动完成”或“自动提示”功能,对吗?
如果仔细观察,您会发现他们基本上在做一些前缀匹配。 您键入的字符串与它们已存储的字符串列表的比较。 那么,如果需要,您将如何自己做呢? 如果您的字符串列表不大,则可以采用任何幼稚的方法来匹配所有字符串。 但这对于大型列表而言并不是那么有效。 有效的方法是使用一些复杂的数据结构,如Trie 。 关于它的详细讨论超出了本文的范围,因此您应该自己深入研究它。
同样,如果需要进行一些后缀匹配,则可以通过将字符串的倒序与实际字符串存储在一起,将问题转换为前缀匹配问题,或者可以使用Suffix Tree帮助。
有时您需要进行一些模式匹配,例如,检查字符串是否是给定字符串的子字符串,或者是否可以在给定字符串中找到模式。 在这种情况下,您需要从各种字符串搜索算法中寻求帮助,然后选择一种满足您需求的算法 。
在某些情况下,当我们运行搜索时,我们不仅要查找与在搜索栏上键入的精确表达式相关的结果,还要与我们使用的其他可能形式的单词相关的结果。 例如,如果我们在搜索栏中键入“运行” ,很有可能希望看到包含“运行”,“运行”形式的结果。 这可以通过两种可能的方法来实现: 词干和词原化 。 这两个过程的目的是相同的: 将每个单词的变形形式简化为一个共同的基数或词根。 尽管此术语在NLP中最受欢迎,但是它也用于某些数据库系统和诸如ElasticSearch之类的文本搜索引擎的全文搜索机制中。
我最后一件事 这里要提到的是“语音字符串匹配”。 语音算法基本上是根据单词的发音来索引单词。 因此,如果要通过单词的发音匹配两个单词,则需要使用语音算法。 语音算法的最常见用法是“拼写检查”,“搜索”等。有几种语音算法可完成诸如soundex , metaphone等的工作。但是请注意,大多数语音算法都是为英语开发的。 因此,它们可能不适用于您期望的其他语言。
! 一次要消化的东西很多。好像我在不详细解释的情况下转储了很多信息吗? 是的,那正是我所做的。 因为我对本文的主要关注是使您熟悉String / Text处理的流行语。 如果您至少了解这些术语,则可以在必要时进行深入研究。
所以,今天就这些。 在评论中留下您的正面/负面反馈。 只是不要太苛刻,因为那会伤害我的自我。 再见 :)
From: https://hackernoon.com/what-every-programmer-should-know-about-string-a6611537f84e