ARTS #013

ARTS #013

Posted by Dan on November 2, 2018

ARTS是由左耳朵耗子--陈皓发起的一个活动: 每周至少做一个leetcode的算法题、阅读并点评至少一篇英文技术文章、学习至少一个技术技巧、分享一篇有观点和思考的文章。(也就是Algorithm、Review、Tip、Share简称ARTS),至少坚持一年。

ARTS 013

这是第13篇

Algorihm 算法题

479. Largest Palindrome Product

Difficulty: Easy

Find the largest palindrome made from the product of two n-digit numbers.

Since the result could be very large, you should return the largest palindrome mod 1337.

Example:

Input: 2

Output: 987

Explanation: 99 x 91 = 9009, 9009 % 1337 = 987

Note:

The range of n is [1,8].

Solution

Language: C

这道题的标签是 容易,对我来说比我之前做的的困难的题还难,刚看到容易的标签之后,没怎么上心,直接用暴力搜索做,遍历所有的数字组合,求乘积,再来判断是否是回文数。结果是超时,我测试了一下当n=5的时候,就要运行几分钟。

int largestPalindrome(int n) {
    if (n==1) {
        return 9;
    }
    long int left = 0;
    for (long int i = 0; i < n; i++) {
        left = left*10 + 9;
    }
    long int right = left;
    long int low = pow(10,n-1);

    int maxpalindrome = 0;

    for (; left >0; left--) {
        right=left;
        for (; right >0; right--) {
            int count = left * right;
            int count1=count;
            int palindrome = 0;
            for (; count >0; ) {
                palindrome = palindrome *10 + count%10;
                count = count/10;
            }

            if (palindrome == count1) {
                if (palindrome > maxpalindrome) {
                    maxpalindrome =palindrome;
                }
            }
        }

    }
        return maxpalindrome%1337;;

只能换个思路了,先找到回文数,然后进行拆分看是否符合要求,结果还是超时,我打印了一下,原来回文数挺多的,

int largestPalindrome(int n) {
    if (n==1) {
        return 9;
    }
    long int left = 0;
    for (long int i = 0; i < n; i++) {
        left = left*10 + 9;
    }
    long int right = left;

    long int low = pow(10,n-1);
    
    for (long int i = left * right; i>0; i--) {
        long int count = i;
        long int count1=count;
        long int palindrome = 0;
        for (; count >0; ) {
            //找回文数  1234 4321
            palindrome = palindrome *10 + count%10;
            count = count/10;
            if (count<palindrome) {
                break;
            }
            
            if (count == palindrome) {
                if (count > right) {
                    break;
                }
                for (long int j = left; j>count1/right; j--) {
                    if (count1%j ==0 ) {
                        return count1 % 1337;
                    }
                  
                }
            }
        }

    }
    return 0;
}

最后我自己还是没想出不超时的答案,下面的答案是别人的,拿来学习一下:


long int creatPalindrome(long int num,int n){
    long int p=num*pow(10,n);
    for(int i=0;i<n;i++){
        p=p+(num/(long int)pow(10,n-i-1))*(long int)pow(10,i);
        num=num%(long int)pow(10,n-i-1);
    }
    return p;
}
int largestPalindrome(int n) {
    if(n==1){return 9;}
    long int p=pow(10,n)-1;
    long int q=p;
    long int temp=pow(10,n-1);
    long int ret=0;
    long int ret1=0;
    while(p>=temp){
        ret=creatPalindrome(p,n);
        for(int i=q;i>=temp;i--){
            ret1=ret/i;
            if(ret1>=i){break;}
            if(ret1>=temp&&ret%i==0)
            {
                return ret%1337;

            }
        }
        p--;
    }
    return NULL;
}


Review

1 .这篇文章来自 https://medium.freecodecamp.org/how-i-launched-an-ios-app-with-a-teenager-926b5a65a991 这篇文章主要讲述了教一个十几岁的孩子实现一个iOS游泳相关APP内容,

https://medium.freecodecamp.org/how-i-launched-an-ios-app-with-a-teenager-926b5a65a991 # How I Launched an iOS App with a Teenager How to go from Scratch to an iPhone app in the App store 如何从无到有地在应用程序商店中使用iPhone应用程序

As a follow up to two of my prior articles, (How to teach programming to teenagers and Beginner’s Guide to Raspberry Pi), I want to share my experiences in helping a teenager go from coding in Scratch to building and deploying an iOS app. 作为我之前两篇文章的后续,(How to teach programming to teenagers and Beginner’s Guide to Raspberry Pi), 我想分享我的经验,帮助一个十几岁的孩子从从零开始编码到建立和部署一个iOS应用程序。

As mentioned in one of my prior articles, I noticed that teenagers have a strong desire to do something that feels more real. So, the natural question that repetitively came up in many of my classes was “Can we build an iPhone App?”. I felt that the time was right for the students to build an app, and I asked them each to pitch an idea. 正如我之前的一篇文章中提到的,我注意到青少年有强烈的愿望去做一些感觉更真实的事情。所以,在我的很多课上,反复出现的一个很自然的问题是“我们能不能开发一个iPhone应用程序?”我觉得现在正是学生们开发应用程序的时候,我让他们每个人提出一个想法。

A week later, one of the students came back with an idea and it seemed really really interesting, so we decided to take some time outside of the regular class time and build it together. And we ended up with a cool app called SwimGrader. 一个星期后,其中一个学生带着一个想法回来了,这个想法看起来真的很有趣,所以我们决定在常规的课堂时间之外花点时间,一起做这件事。最后我们开发了一个很酷的应用程序,叫做“游泳分级器”。

How did SwimGrader come about? SwimGrader是关于什么的

My student is an avid swimmer and has always been curious how good his swimming is. Assessing your own swimming ability is not really obvious, and you often need some expert to tell you how good you are. 我的学生酷爱游泳,总是好奇他的游泳技术有多好。评估自己的游泳能力并不是很明显,你经常需要一些专家来告诉你你有多优秀。

We all know that lowering lap time is the goal most athletes shoot for, so a lot of people attempt to do that. However, it is quite hard to know in detail what you must work on to achieve lower lap times. Of course, you can just try to kick faster and practice more to gain more swimming muscles, but that usually is not the best way to improve your swimming. 我们都知道,降低圈速是大多数运动员的目标,所以很多人都试图这样做。然而,要知道你必须做什么才能达到较低的圈速是相当困难的。当然,你可以尝试更快的踢腿和更多的练习来获得更多的游泳肌肉,但这通常不是提高你的游泳的最好方法。

Coming from this, my student thought that people needed something that could pinpoint an area of swimming they should work on next. So, his brilliant idea was to build an app that could assess various aspects of your swimming and tell you which area you should work to improve. 从这一点出发,我的学生认为人们需要一些东西来确定他们下一步应该研究的游泳领域。所以,他的绝妙想法是开发一款应用程序,可以评估你游泳的各个方面,并告诉你应该改进哪个领域。

Knowing from experience how hard it is to improve my swimming, I was really impressed by his idea. It was nothing that I had heard of before and it had a specific use case that could potentially benefit a lot of people. However, since my student had never built an iPhone app before, we decided to work on it together from scratch. 从经验得知提高我的游泳水平有多难,他的想法给我留下了深刻的印象。这不是我以前听说过的,它有一个特定的用例,可能会让很多人受益。然而,由于我的学生之前从未开发过iPhone应用程序,我们决定一起从头开始。

Getting started

Not being a competitive swimmer myself and also thinking that it would be a good thought exercise, I asked my student to come up with the design of the app and the metrics we could use to grade the swimmer in the app. 我自己并不是一个有竞争力的游泳运动员,也认为这将是一个很好的思考练习,我让我的学生提出应用程序的设计,以及我们可以用来在应用程序中给游泳运动员打分的指标。

This process ended up to be a really good learning experience. Not only did this exercise helped the student iron out the details of the project, but it also kept my and my student’s expectations in line. As mentioned in my articles about teaching teenagers, teenagers have high expectations about doing anything with programming. So, after talking through every detail from which data to collect, which pages to create, how each page transition works and which metrics to show, both of us were to clearly set our goals and our expectations. 这个过程最终成为一个很好的学习经历。这个练习不仅帮助学生解决了项目的细节问题,也让我和学生的期望保持一致。正如我在关于青少年教学的文章中提到的,青少年对编程有很高的期望。因此,在详细讨论了要收集哪些数据、要创建哪些页面、每个页面转换如何工作以及要展示哪些指标之后,我们都明确了自己的目标和期望。

And knowing the exact end-product we were planning to make helped the student stay constantly engaged. 知道我们计划生产的确切的最终产品帮助学生保持持续的参与。

Digressing a little bit from the main topic, we often learn things that we don’t know when we will ever apply in our lives. This can make us feel like we are walking through a long dark tunnel with no light at the end. 我们经常会学到一些我们不知道什么时候能应用到生活中的东西。这能让我们感觉像是在穿过一条长长的黑暗隧道,尽头没有灯光。

This is especially true when you are younger, as you are most likely being told to learn certain things. I believe that this causes many students to not get excited about what they learn. I learned that setting the right expectations by showing the end of the journey of a learning exercise really helps motivate students and increases the efficiency of the learning exercise itself. 这在你年轻的时候尤其正确,因为你很可能被告知要学习某些东西。我认为这导致许多学生对他们所学的东西不感兴趣。我了解到,通过展示学习过程的终点来设定正确的期望,确实有助于激发学生的积极性,并提高学习过程本身的效率。

So, back to the design and the metrics of the app that the student suggested: my student first suggested that the app, in general, should not add any overhead for the swimmer. He wanted to build an app that would be able to collect statistics without hampering the swimmer’s performance. 所以,回到学生建议的应用程序的设计和指标:我的学生首先建议应用程序,一般来说,不应该为游泳者增加任何开销。他希望开发一款能够收集统计数据而不会影响游泳运动员表现的应用程序。

The student already had a measuring device in mind to serve this exact purpose, which I will share in the next section. After some discussion to come up with a minimal viable product, we decided that we should focus on collecting two specific metrics: head bops and turn speed. 这个学生心里已经有了一个测量设备来达到这个目的,我将在下一节中与大家分享。经过一些讨论,我们得出了一个最小可行的产品,我们决定我们应该集中收集两个具体的指标:头防喷器和转弯速度。

Since head bops are a mostly extraneous movement that can reduce the efficiency of swimming, if we can simply count the number of head bops within some time interval, we thought that we could suggest a reduction in extraneous head movements. 由于头部爆震是一种可以降低游泳效率的无关运动,如果我们能在一段时间内简单地数一数头部爆震的数量,我们认为我们可以建议减少无关的头部运动。

We also agreed that fast turns are necessary for reducing lap times. So, if we could measure the time it takes the swimmer to make a turn at the end of the lane, we could grade the swimmer based on time. 我们也同意快速转弯对于缩短圈速是必要的。所以,如果我们能测量游泳者在泳道末端转弯所花费的时间,我们就能根据时间给游泳者打分。

Given this design and the idea, we only needed to start implementing it with the right sensor. 有了这个设计和想法,我们只需要开始用合适的传感器来实现它。

So, which hardware made SwimGrader possible?那么,哪一种硬件使游泳评分成为可能呢?

Although the latest iPhones are waterproof, swimmers probably don’t want to risk taking their super expensive iPhones into the pool. So, my student suggested that we use a sensor from mbientlab and enclose it in a waterproof case. 虽然最新款的iphone是防水的,但游泳者们可能不想冒险把超级昂贵的iphone带入泳池。所以,我的学生建议我们使用一个来自mbientlab的传感器,并将其封装在一个防水外壳中。

This sensor allows you to collect various data from the environment and from your movements, as it houses an accelerometer, a gyroscope, a barometer, a thermometer and so on. Also, they have some sample code that you can use to bootstrap your application so you can immediately collect the data of interest. 这个传感器允许你从环境和你的运动中收集各种数据,因为它包含一个加速度计,一个陀螺仪,一个气压计,一个温度计等等。此外,它们还有一些示例代码,您可以使用这些代码引导应用程序,以便立即收集感兴趣的数据。

So, our idea was to put the sensor inside his swimming cap. He felt that this would minimally impact the swimmers’ ability to swim, which I agreed with. We immediately purchased two of these sensors and started building our app. I will not go over the details of building a simple multi-page iOS app using Swift, because they have covered in thousands of other articles (here is a good medium article that presents many of them). 所以,我们的想法是把传感器放在他的泳帽里。他觉得这将会对游泳者的游泳能力产生最小的影响,我同意。我们立即购买了两个这样的传感器,并开始构建我们的应用程序。我不会详细介绍使用Swift构建一个简单的多页iOS应用程序的细节,因为它们已经涵盖了数千篇其他文章(这里有一篇不错的中等文章,其中有很多)。

SwimGrader App Window

Introducing SwimGrader

So, after hours of programming and going through Apple to get our app approved for the App Store, we were finally able to launch SwimGrader. It was really surprising to see this, because I only helped with the initial setup of the project, which consisted of setting up a single page app Swift project and helping with adding buttons and text fields, and simple hardware integration to retrieve data from the sensor. 所以,经过数小时的编程,并通过苹果公司,我们的应用程序获得了应用商店的批准,我们终于可以推出“游泳分级器”了。看到这个真的很让人惊讶,因为我只帮助了项目的初始设置,包括设置一个单一页面的app Swift项目,帮助添加按钮和文本字段,以及从传感器检索数据的简单硬件集成。

To give a sense of how easy the hardware integration was, here is a snippet of code to make the LED on the sensor flash green. Retrieving data was just as simple, as can be seen by the example below. 为了说明硬件集成是多么容易,这里有一个使传感器上的LED显示为绿色的代码片段。检索数据非常简单,如下面的示例所示。

import MetaWear
import MetaWearCpp
MetaWearScanner.shared.startScan(allowDuplicates: true) { (dev) in
    // We found a MetaWear board, see if it is close by
    if dev.rssi.intValue > -50 {
        // We found a MetaWear board!
        MetaWearScanner.shared.stopScan()
        // Connect to the board we found
        dev.connectAndSetup().continueWith { t in
            if let error = t.error {
                // Sorry we couldn't connect
                print(error)
            } else {
                // We are connected! Flash its LED!
                var pattern = MblMwLedPattern()
                mbl_mw_led_load_preset_pattern(
                    &pattern, MBL_MW_LED_PRESET_PULSE)
                mbl_mw_led_stop_and_clear(device.board)
                mbl_mw_led_write_pattern(
                    device.board, &pattern, MBL_MW_LED_COLOR_GREEN)
                mbl_mw_led_play(device.board)
            }
        }
    }
}

Given only a limited about of help, my student went far beyond my expectations to build a grading algorithm and a graphical interface. He retrieved the X, Y, Z data from the sensor and gave a grade on how much the head moved in each direction. He searched online for a graphing library on iOS and displayed what his sensor reported. And, after finishing his app, he went ahead and tested his app in the pool! 由于帮助有限,我的学生远远超出了我的期望,建立了一个评分算法和图形界面。他从传感器中获取了X, Y, Z数据,并给出了头部在每个方向移动的程度。他在网上搜索iOS上的图形库,并显示传感器报告的内容。完成应用程序后,他继续在水池中测试他的应用程序!

It is an effort by a middle school student, so it’s not going to look fancy like Clash of Clans. However, I think it is really impressive, coming from a young student who has never built an iPhone app before! After finishing this, the student asked me, 这是一个中学生的努力,所以它看起来不像《部落战争》那样花哨。然而,我认为这真的是令人印象深刻的,来自一个从未开发过iPhone应用程序的年轻学生!做完这些后,学生问我,

Can we build an Apple Watch App for this? 我们可以为此开发一个Apple Watch应用程序吗?

I told him that he could definitely build an Apple Watch version of the app in the future, but that he could probably build it without my help :). 我告诉他,他将来肯定能开发出Apple Watch版本的应用程序,但他可能不需要我的帮助就能开发出来:)。

Final Thoughts

As grown-ups, I think it is really hard to keep our ideas fresh, wild and up-to-date. So, I think it’s really educational to hear what these young students have to say and to support what they want to do in all the ways we can. 作为成年人,我认为让我们的思想保持新鲜、狂野和与时俱进真的很难。所以,我认为听取这些年轻学生的意见并支持他们想做的事情是非常有教育意义的。

Not only do these opportunities open the gate to building new and exciting products, but supporting students to pitch and build their own ideas gives them the best educational experiences. Seeing my student asking people to download his app makes me smile. I am hoping that I can maybe build a cool app someday and showcase it to my friends. Although, my student just beat me to that :) 这些机会不仅为开发新的和令人兴奋的产品打开了大门,而且支持学生推销和建立他们自己的想法给他们最好的教育体验。看到我的学生让人们下载他的应用程序,我笑了。我希望有一天我能开发一个很酷的应用程序,并向我的朋友展示。虽然,我的学生只是抢在我前面:)

On a side note, I learned that building a cool iOS app is easier than ever. There are so many articles helping you build apps for every possible purpose: games, single view apps, social network apps and many more. Also, there is more hardware than ever that you can easily hook up to your phone and extend the capabilities of your phone. 顺便说一下,我了解到构建一个很酷的iOS应用程序比以前更容易。有很多文章可以帮助你为所有可能的目的开发应用程序:游戏、单视图应用程序、社交网络应用程序等等。此外,现在有了更多的硬件,你可以很容易地连接到你的手机,并扩展你的手机的功能。

I hope I can soon share experiences of building my own app. I am just worried if my students will find my app cool… 我希望我能尽快分享自己开发应用的经验。我只是担心我的学生是否会觉得我的应用很酷……

Thank you for reading this article! I hope I can convince you to work with your students or your children and start building a simple app! I am also open to hearing about your cool app ideas. 感谢您阅读本文!我希望我能说服你与你的学生或你的孩子一起工作,并开始建立一个简单的应用程序!我也愿意听听你的酷应用的想法。

  1. 本周翻译了第一章的上周未翻译的部分,第一章已经翻译完成了: https://dandan2009.github.io/2018/10/26/Instruments-chinese-translation/

TIPS

本周遇到一个NSCharacterSet的问题,就研究了一下这个NSCharacterSet,发现NSCharacterSet功能还是挺强大的。

NSCharacterSet

An object representing a fixed set of Unicode character values for use in search operations. 表示用于搜索操作的一组固定Unicode字符值的对象。

Overview

An NSCharacterSet object represents a set of Unicode-compliant characters. NSString and NSScanner objects use NSCharacterSet objects to group characters together for searching operations, so that they can find any of a particular set of characters during a search. The cluster’s two public classes, NSCharacterSet and NSMutableCharacterSet, declare the programmatic interface for static and dynamic character sets, respectively. NSCharacterSet对象表示Unicode-compliant(compliant兼容)的字符集合。NSString和NSScanner对象使用NSCharacterSet对象将字符分组以进行搜索操作,这样它们就可以在搜索过程中找到特定的一组字符。集群的两个公共类NSCharacterSet和NSMutableCharacterSet分别声明静态和动态字符集的编程接口。

The objects you create using these classes are referred to as character set objects (and when no confusion will result, merely as character sets). Because of the nature of class clusters, character set objects aren’t actual instances of the NSCharacterSet or NSMutableCharacterSet classes but of one of their private subclasses. Although a character set object’s class is private, its interface is public, as declared by these abstract superclasses, NSCharacterSet and NSMutableCharacterSet. The character set classes adopt the NSCopying and NSMutableCopying protocols, making it convenient to convert a character set of one type to the other. 使用这些类创建的对象被称为字符集对象(当不产生混淆时,仅仅作为字符集)。由于类集群的性质,字符集对象不是NSCharacterSet或NSMutableCharacterSet类的实际实例,而是它们的一个私有子类的实例。虽然字符集对象的类是私有的,但是它的接口是公共的,由这些抽象超类NSCharacterSet和NSMutableCharacterSet声明。字符集类采用了NSCopying和NSMutableCopying协议,使得将一种类型的字符集转换为另一种类型的字符集变得很方便。

The NSCharacterSet class declares the programmatic interface for an object that manages a set of Unicode characters (see the NSString class cluster specification for information on Unicode). NSCharacterSet’s principal primitive method, characterIsMember:, provides the basis for all other instance methods in its interface. A subclass of NSCharacterSet needs only to implement this method, plus mutableCopyWithZone:, for proper behavior. For optimal performance, a subclass should also override bitmapRepresentation, which otherwise works by invoking characterIsMember: for every possible Unicode value. NSCharacterSet类声明一个对象的编程接口,该对象管理Unicode字符集合(有关Unicode的信息,请参阅NSString类集群规范)。NSCharacterSet的主基元方法characterIsMember:为它的接口中所有的实例方法提供基础。NSCharacterSet的一个子类只需要实现这个方法,加上mutableCopyWithZone:方法,就可以获得正确的行为。为了获得最佳性能,子类还应该覆盖位图表示,否则可以调用characterIsMember:对于所有可能的Unicode值。

NSCharacterSet is “toll-free bridged” with its Core Foundation counterpart, CFCharacterSetRef. See Toll-Free Bridging for more information on toll-free bridging. NSCharacterSet是“toll-free bridged”与它的核心基础对等物CFCharacterSetRef。有关toll-free bridged的更多信息,请参阅toll-free bridged。

NSCharacter​Set 可以方便的对字符串进行处理

比如判断一个字符串是否以数字开头


NSString * string = "3dfdfsa";
unichar c = [string characterAtIndex:0];
if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:c]) {
return YES;
} else {
return NO;
}
}

NSString中两个跟NSCharacterSet有关的方法: //根据字符集来清理字符串两端的字符

  • (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set; //根据字符集separator来分割字符串
  • (NSArray<NSString *> *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator;

NSString *string = @”123abc123”;

string = [string stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]];

NSLog(@”%@”,string);//输出abc

//字符集的二进制数据,用于传输、归档、保存成文件
@property (readonly, copy) NSData *bitmapRepresentation;


//一个除了数字字符之外的所有字符的字符集
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]


//判断aCharacter是否包含在字符集中
- (BOOL)characterIsMember:(unichar)aCharacter;
//功能貌似是一样的,入参是UTF-32的字符???不知道这两个方法的区别,知道的朋友不吝赐教
- (BOOL)longCharacterIsMember:(UTF32Char)theLongChar;

//判断theOtherSet是不是自身的子集
- (BOOL)isSupersetOfSet:(NSCharacterSet *)theOtherSet;


- (BOOL)hasMemberInPlane:(uint8_t)thePlane;


对字符串进行编码:

NSString * string =  @"11 =Essential ,Coding Interview Questions + Coding Exercises!" ;
[string  stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];

alphanumericCharacterSet 所有数字和字母(大小写不分)

编码后的结果就是:

11%20%3DEssential%20%2CCoding%20Interview%20Questions%20%2B%20Coding%20Exercises%21

可以看到上面的结果对所有数字和字母之外的所有字符都进行了编码。

然后再看下invertedSet的作用

[string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet].invertedSet]

加上invertedSet之后的结果如下:


%31%31 =%45%73%73%65%6E%74%69%61%6C ,%43%6F%64%69%6E%67 %49%6E%74%65%72%76%69%65%77 %51%75%65%73%74%69%6F%6E%73 + %43%6F%64%69%6E%67 %45%78%65%72%63%69%73%65%73!

可以看到只对数字和字母进行了编码。

也就是说NSCharacterSet可以方便的指定对什么字符进行编码。 也可以使用characterSetWithCharactersInString进行完全自定义编码字符

NSCharacterSet *dd = [NSCharacterSet characterSetWithCharactersInString@"^~_>+=\"#%/<>?@\\^`{|}"];

相关博客:https://nshipster.cn/nscharacterset/

常用API

/** 常用快捷方法集合 (常用的,已满足大多数需求) */ (NSCharacterSet *)controlCharacterSet; // 控制字符,包括换行符(\n)、制表符(\t)等,具体有哪些,不清楚 (NSCharacterSet *)whitespaceCharacterSet; //空格 (NSCharacterSet *)whitespaceAndNewlineCharacterSet;//空格和换行符 (NSCharacterSet *)decimalDigitCharacterSet; //0-9的数字 (NSCharacterSet *)letterCharacterSet; //所有字母 (NSCharacterSet *)lowercaseLetterCharacterSet; //小写字母 (NSCharacterSet *)uppercaseLetterCharacterSet; //大写字母 (NSCharacterSet *)nonBaseCharacterSet; //非基础 (NSCharacterSet *)alphanumericCharacterSet; //所有数字和字母(大小写不分) (NSCharacterSet *)decomposableCharacterSet; //可分解 (NSCharacterSet *)illegalCharacterSet; //非法 (NSCharacterSet *)punctuationCharacterSet; //标点符号 指在用于分隔文字的符号 (NSCharacterSet *)capitalizedLetterCharacterSet; //大写 (NSCharacterSet *)symbolCharacterSet; // 符号字符,除了标点符号之外,例如¥、$这样的符号 (NSCharacterSet *)newlineCharacterSet NS_AVAILABLE(10_5, 2_0);//换行符

/** 根据一个给定的字符串获取一个NSCharacterSet对象 */

  • (NSCharacterSet *)characterSetWithCharactersInString:(NSString *)aString;

/** 相反字符串限制 【具体见接下的例子】 */ @property (readonly, copy) NSCharacterSet *invertedSet;

  • characterIsMember:

NSCharacterSet这个类的功能有点类似于正则 : https://nshipster.cn/nscharacterset/

NSString 与 Unicode: https://objccn.io/issue-9-1/#peculiar-unicode-features

iOS英文博客:https://nshipster.com/ 上面对应的中文版:https://nshipster.cn/

如果你对什么是字符编码搞不清楚的话(即使你有很好的专业知识),那么你应该抓住这次机会反复阅读Joel Spolsky的这篇经典的文章:https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/

Share

  1. 先分享个可以查看App Store下载量比较大或比较流行的APP用了哪些第三方库的网站:https://www.appsight.io

  2. 再分享几个学习算法的网站,有的视频网站,有的是带动画的:

    • 印度小伙的算法视频 ,英语算法同时学习:https://www.youtube.com/channel/UCx-kFfzekMbhODaBss-ZnsA

    • 算法教程 : https://notes.diguage.com/mysql/#_%E6%97%B6%E9%97%B4%E5%A4%8D%E6%9D%82%E5%BA%A6

    • 图解算法: https://visualgo.net/zh
    • 这个动画可以帮你理解算法: https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

    • 常用算法的动画解释:https://www.toptal.com/developers/sorting-algorithms

    • 这个动画也不错,非常炫:http://sorting.at/
  3. 再推荐个数据库课程: https://15445.courses.cs.cmu.edu/fall2017/schedule.html