Ruby 的版本管理有rvm
和rbenv
。现在主要的是用rbenv
。
brew install rbenv
rbenv versions
rbenv use 2.7.2
brew install pyenv
pyenv versions
pyenv global
pyenv local
yarn global add n
n
Hash
{a: 1, b: 2, c: 3}
Dictionary
{'a': 1, 'b': 2, 'c': 3}
无论是字典dict
还是集合set
,背后都是散列表数据结构,结果就是占用内存很大,能够快速判断 key 是否存在。
// Object
{'a': 1, 'b': 2, 'c': 3}
// ES6 Map
const mapper = new Map([['1', 'a'], ['2', 'b']]);
// Map
ages := make(map[string]int) // 不能够初始化为nil,否则不能够赋值了
ages := map[string]int{
"alice": 31,
"charlie": 34,
}
true
false
True
False
true;
false;
true
false
true
false
arr = [1,2,3]
arr[1..] # [2, 3]
arr[-1] # [3]
arr[1..2] # [2, 3]
# 但是不支持 arr[::2]这样的操作
arr + [4, 5, 6] # [1,2,3,4,5,6]
arr = [1,2,3]
arr[1:] # [2, 3]
arr[:2] # [1, 2]
arr[::2] # [1, 3]
arr + [4, 5, 6] # [1,2,3,4,5,6]
for i in arr:
print(i)
Python 里面还有一种数据类型叫元组。元组是不可变的,对应的就是列表是可变的。
此外,如果列表的元素都是数字,可以用array.array
更为高效。
from array import array
from random import random
floats = array('d', (random() for i in range(10**7)))
fp = open('floats.bin', 'wb')
floats.tofile(fp)
var arr = [1,2,3]
arr.slice(0, 2) // [1, 2]
[...arr, ...arr] // [1,2,3,1,2,3]
// Go语言里面很少使用数组,因为是固定长度的。
q := [...]int{1, 2, 3}
fmt.Printf("%T\n", q) // "[3]int"
fmt.Printf("%v\n", q) // "[1,2,3]"
// 相对应的是Slice,动态序列,和Python一样,支持各种切片操作
data := []string{"one", "", "three"}
fmt.Printf("%q\n", data) // `["one" "three" "three"]`
fmt.Printf("%q\n", data[:2]) // `["one" ""]`
numbers := []int{1,2}
numbers = append(numbers, 3, 4) // [1,2,3,4]
fmt.Printf("%v\n", numbers) // "[1,2,3,4]"
// 切片
let s = String::from("hello world");
// 引用了s的一部分
let hello = &s[0..5];
let world = &s[6..11];
// 包括最后一个字符
let len = s.len();
let slice = &s[4..len];
let slice = &s[4..];
2.6.6 :027 > a = [1,2,3]
=> [1, 2, 3]
2.6.6 :028 > b = a
=> [1, 2, 3]
irb(main):011:0> a.object_id
=> 70076125215020
irb(main):012:0> b.object_id
=> 70076125215020
>>> a = [1,2,3]
>>> b = a
>>> id(b)
4315631168
>>> id(a)
4315631168
>>> a[2] = 4
>>> a
[1, 2, 4]
>>> b
[1, 2, 4]
# 一般不这样复制数组,而是通过一下方法
>>> a = [1,2,3]
>>> b = list(a)
>>> id(a)
4408133312
>>> id(b)
4408170944
a := []int{1,2,3}
b := a
fmt.Printf("%v\n", a) // [1,2,3]
fmt.Printf("%v\n", b) // [1,2,3]
a = append(a, 4)
fmt.Printf("%v\n", a) // [1,2,3,4]
fmt.Printf("%v\n", b) // [1,2,3]
// 这里需要注意的是,a和b共享了同一片内存空间,即[1,2,3]。
// 任何这里的修改都会互相影响。
if true
puts 'yes'
else
puts 'no'
end
if True:
print('yes')
elif False:
print('no')
else:
print('n/a')
if (true) {
console.log("yes");
} else {
console.log("no");
}
s := "bingo"
if s != "" {
fmt.Println("yes")
} else {
fmt.Println("no")
}
(0..10).each do |i|
puts i
end
{a: 1, b: 2}.each do |k, v|
puts [k, v]
end
for i in [1,2,3]:
print(i)
for i in range(10):
print(i)
for i in count(start=0, step=1):
print(i)
d = {'x': 1, 'y': 2, 'z': 3}
for k, v in d.items():
print(k, v)
while True:
quotient = num // output_base
remainder = num % output_base
output.append(remainder)
num = quotient
if quotient == 0:
break
还可以通过推导式把列表转换成为字典
items = [
('apple', 10),
('orange', 5),
('banana', 7)
]
{item: price for item, price in items}
,或者集合。
from unicodedata import name
{ chr(i) for i in range(32, 256) if 'SIGN' in name(chr(i), '')}
let arr = ["a", "b", "c"];
for (let [k, v] of arr.entries()) {
console.log(k);
console.log(v);
}
let dict = { a: 1, b: 2, c: 3 };
for (let [k, v] of Object.entries(dict)) {
console.log(k);
console.log(v);
}
// Only for loop in Go
sum := 1
for sum < 100 {
sum += 1
}
fmt.Println(sum)
// Infinite loop
// while true in Ruby
for {
// do something
}
// each
kvs := map[string]string{"name": "Amy", "lastName": "Amy"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
// 如果是数组,第一个就是index
arr := []string{"a", "b", "c", "d", "e"}
for i, v := range arr {
fmt.Println(i, v)
}
# 在Ruby里面,函数和方法一般是同一个东西。
# 在英语里面,Function是独立的,可以调用的。Method是在类里面定义的函数,需要通过实例才可以调用它。
# 函数不是第一公民
# 这就意味着你不能够把函数赋值给变量,当作参数传入或者返回。
# 虽然可以通过symbol,或者lambda的方式来实现,但是总觉得是剑走偏锋了,一般都不这么用
# 函数是第一公民
# 在Python里面最典型的例子就是装饰器。装饰器其实就是把被修饰的函数B当做参数传入装饰器函数A,然后在返回一个新的函数C。
# 这样在执行函数B的时候,实际上是执行函数C,所以你可以在C里面定义额外的操作,比如给方法计时
# 你还可以嵌套多次装饰器,实现参数化的装饰器
// 一般没有提第一公民这事,但是的确存在
// 最显然的例子就是函数定义有两种方式,一种是函数声明,另外一种就是函数表达式
// 函数是第一公民
// 这就意味着函数可以当做值一样地处理
// 可以当作参数传入其他函数,也可以赋值给变量
// 甚至可以把一个实例的方法绑定给某个变量,调用这个变量其实就是调用这个实例的方法
p := Point{1, 2}
q := Point{4, 6}
distanceFromP := p.Distance // method value
fmt.Println(distanceFromP(q)) // "5"
// 如果你是绑定struct里面的方法,那就需要第一个参数需要指定receiver
// 就像Python里面定义方法的时候,第一个参数是`self`或者`cls`
distance := Point.Distance // method expression
fmt.Println(distance(p, q)) // "5"
# 如果理解透,其实每个类是Class的一个实例
class A
end
a = A.new # <A:0x00007fb508870018>
a.class # A
A.class # Class
# 所以,所谓的类方法,实际上其实也是实例(Class的一个实例A)方法
# 定义类方法,有好几种方法
class A
def self.m1
puts 'm1'
end
class << self
def m2
puts 'm2'
end
end
end
A.instance_eval do
def m3
puts 'm3'
end
end
module M4
def m4
puts 'm4'
end
end
# A.extend M4
# 或者像下面那样,记住隐式的self
class A
extend M4
end
# 调用的时候直接A.m1就行了
# 记住,A其实也是一个实例
from math import hypot
class Vector:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def __repr__(self):
return 'Vector(%r, %r)' % (self.x, self.y)
def __abs__(self):
return hypot(self.x, self.y)
def __bool__(self):
return bool(abs(self))
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
class Robot {
name: string;
static availableNames: string[];
constructor() {
this.name = Robot.generateName();
}
public resetName(): void {
this.name = Robot.generateName();
}
public static releaseNames(): void {
Robot.availableNames = [];
}
public static generateName(): string {
if (
Robot.availableNames === undefined ||
Robot.availableNames.length === 0
) {
Robot.availableNames = [];
let letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
let numbers = "0123456789".split("");
for (const a of letters) {
for (const b of letters) {
for (const x of numbers) {
for (const y of numbers) {
for (const z of numbers) {
Robot.availableNames.push([a, b, x, y, z].join(""));
}
}
}
}
}
// shuffle the array list
for (let i = Robot.availableNames.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[Robot.availableNames[i], Robot.availableNames[j]] = [
Robot.availableNames[j],
Robot.availableNames[i],
];
}
}
return Robot.availableNames.pop() as string;
}
}
// https://googlechrome.github.io/samples/classes-es6/
# method_missing
# define_method
# include / included
# prepend / prepended
# extend / extended
self.send(k)
getattr(self, k)()
puts 's'
print('s')
console.log("s");
s := "s"
fmt.Println(s)
irb(main):001:0> a = [3,2,1]
=> [3, 2, 1]
irb(main):002:0> a.sort
=> [1, 2, 3]
irb(main):003:0> a
=> [3, 2, 1]
a_list = [3,2,1]
a_list.sort() # None
a_list # [1,2,3]
如果你不想影响a_list
,则可以用sorted
方法。
a_list = [3,2,1]
sorted(a_list)
# [1,2,3]
const arr = ["peach", "straw", "apple", "spork"];
arr.sort();
const arr = [5, 2, 3, 7, 9, 1];
arr.sort((a, b) => b - a);
import "sort"
strs := []string{"c", "a", "b"}
sort.Strings(strs)
fmt.Println("Strings:", strs)
ints := []int{7, 2, 4}
sort.Ints(ints)
fmt.Println("Ints: ", ints)
[['a', 7], ['b', 2]].sort_by { |k, v| v } => [["b", 2], ["a", 7]]
# Ruby的类里面如果include了Enumerable并定义了<=>方法,那他们的实例就是可以比较的
# 具体的比较方法通过定义的<=>来实现的
# 比如下面的就是一个简单的二叉树节点的比较
class Bst
include Enumerable
attr_reader :left, :right, :data
def initialize(new_data)
@data = new_data
end
def insert(new_data)
if new_data <= @data
@left ? @left.insert(new_data) : @left = Bst.new(new_data)
else
@right ? @right.insert(new_data) : @right = Bst.new(new_data)
end
self
end
def each(&block)
return to_enum unless block_given?
@left&.each(&block)
yield @data
@right&.each(&block)
self
end
def <=>(other)
@data <=> other.data
end
def predecessor(key)
self.each_cons(2).select { |e| e.last == key }.map(&:first)[0]
end
def successor(key)
self.each_cons(2).select { |e| e.first == key }.map(&:last)[0]
end
end
>>> a = [['a', 7], ['b', 2]]
>>> a.sort(key=lambda e: (e[1], e[0]), reverse=True)
>>> a
[['b', 2], ['a', 7]]
# Python 好像不屑于Ruby的spaceship operator
# 如果需要排序,用自定义排序就可以搞定了
// 如果记得Ruby中的宇宙飞船符的话,下面的通过函数自定义排序其实也是类似的
var items = [
{ name: "Edward", value: 21 },
{ name: "Sharpe", value: 37 },
{ name: "And", value: 45 },
{ name: "The", value: -12 },
{ name: "Magnetic", value: 13 },
{ name: "Zeros", value: 37 },
];
// sort by value
items.sort(function (a, b) {
return a.value - b.value;
});
// sort by name
items.sort(function (a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
// Need to implement sort.Interface - Len, Less, and Swap on type byLength
type byLength []string
func (s byLength) Len() int {
return len(s)
}
func (s byLength) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s byLength) Less(i, j int) bool {
return len(s[i]) < len(s[j])
}
func main() {
fruits := []string{"peach", "banana", "kiwi"}
sort.Sort(byLength(fruits))
fmt.Println(fruits)
}
arr = [] # => []
arr.push(1) # => [1]
arr.unshift(2) # => [2, 1]
arr.shift # => 2
arr.pop # => 1
arr = []
arr.append(1)
arr.insert(0, 2) # => [2, 1]
arr.pop(0) # => 2
arr.pop() # => 1
var arr1 = [0, 1, 2];
arr1.push(3);
var arr2 = [4, 5, 6];
arr1.push(...arr2);
arr1.pop();
arr1.shift();
// go 没有pop方法,只能够自己写
func pop(alist *[]int) int {
f:=len(*alist)
rv:=(*alist)[f-1]
*alist=append((*alist)[:f-1])
return rv
}
func main() {
n:=[]int{1,2,3,4,5}
fmt.Println(n)
last:=pop(&n)
fmt.Println("last is",last)
fmt.Printf("list of n is now %v\n", n)
}
'13243432432'.scan(/\d/) => ["1", "3", "2", "4", "3", "4", "3", "2", "4", "3", "2"]
m = /\A(\d{3})(\d)/.match('13243432432') => #<MatchData "1324" 1:"132" 2:"4">
m[0] # "1324"
m[1] # "132"
import re
re.findall(r'\d', '1234232432')
# ['1', '2', '3', '4', '2', '3', '2', '4', '3', '2']
import re
s = 'a1b2c3'
s = 'a1b#2c3'
m = re.match(r'([^#]*)#(.*)', s)
m.group() # => 'a1b#2c3'
m.group(1) # => 'a1b'
m.group(2) # => '2c3'
const regex = /[a-zA-Z]/g;
const matched_chars = "abcdefg".match(regex);
// ['a', 'b', 'c', 'd', 'e', 'f', 'g']
lst.find { |e| e == i }
next(x for x in seq if predicate(x))
const array1 = [5, 12, 8, 130, 44];
const found = array1.find((element) => element > 10);
// 12
[1,2,3] + [4, 5, 6]
b = [1,2,3]
b.extend([5,4,6])
b + [7,8,9]
var a = [1, 2, 3];
// don't use + as it will return '1,2,34,5,6'
a.push(...[4, 5, 6]);
a; //[1,2,3,4,5,6]
# 返回一个整数identifier,可以用来判断两个变量是否是同一个对象
a.object_id
id(a)
// no such method
'str'.class
type('123')
'123'.__class__
[1,1,1].uniq => [1]
list(set([1,1,1]))
let arr = [1,2,3,1,2,3]
[...new Set(arr)]
// [1, 2, 3]
[1,2,3].map { |e| e * 3 }
一般建议用 Python 自带的列表推导,而不是用lambda
,因为列表推导更加直观。
list(map(lambda x: x * 3, [1,2,3]))
[i * 3 for i in [1,2,3]]
上面的列表推导,还可以用元组来表示。两者的区别在于,列表推导是每个元素真实存在,而元组是迭代的时候才会生成下一个。所以,列表推导比较占内存,但是因为数据都在内存里面,所以速度比元组推导快。
[1, 2, 3, 4, 5].map((x) => x * 2);
(-5..5).select { |x| x < 0 }
一般建议用 Python 自带的列表推导,而不是用lambda
,因为列表推导更加直观。
less_than_zero = list(filter(lambda x: x < 0, range(-5, 5)))
[e for e in range(-5, 5) if e < 0]
Array.from({ length: 5 }, (v, i) => i).filter((x) => x % 2 === 0);
// [0, 2, 4]
[1,2,3].reduce(0) { |sum, x| sum + x }
[1,2,3].reduce(&:+)
from functools import reduce
reduce(lambda sum, x: sum + x, [1,2,3], 0)
const array1 = [1, 2, 3, 4];
array1.reduce((sum, x) => sum + x);
[1,2,3].all { |e| e.even? }
all(len(g) % 2 == 0 for g in groups)
[2, 4, 6].every((x) => x % 2 === 0);
[1,2,3].any? { |e| e > 1 } => true
any(x > 3 for x in [1,2,3]) # False
[2, 4, 6].some((x) => x % 2 === 0);
a = {name: 'phx', age: 12}
a.merge({gender: 'male'})
In [51]: a = {'name': 'phx', 'age': 12 }
In [52]: a
Out[52]: {'name': 'phx', 'age': 12}
In [53]: a.update({'gender': 'male'})
In [54]: a
Out[54]: {'name': 'phx', 'age': 12, 'gender': 'male'}
var a = { a: 1 };
var b = Object.assign(a, { b: 2 });
// {a: 1, b: 2}
[1,2,3,4,5,6,7,1,3].group_by {|e| e}.map { |k, v| [k, v.size]}.to_h
import collections
dict(collections.Counter([1,2,3,4,5,6,7,1,3]))
[1, 2, 3, 4, 5, 6, 7, 1, 3].reduce((acc, x) => {
if (!acc[x]) acc[x] = 0;
acc[x] += 1;
return acc;
}, {});
(1..5).to_a
list(range(10))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list(range(1, 10))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Array.from({ length: 5 }, (v, i) => i);
// [0, 1, 2, 3, 4]
'foo'.chars
[char for char in 'foo']
Array.from("foo");
"foo".chars()
begin
1/0
rescue Exception => e
p e
end
try:
y = ALPHABET.index(char)
except ValueError:
return char
('a'..'z').to_a
from string import ascii_lowercase
ALPHABET = list(ascii_lowercase)
[1,2,3].join('')
''.join([1,2,3])
[1, 2, 3].join("");
7.to_s(2)
"{0:b}".format(7 % 256)
(10).toString(2);
'101'.to_i(2)
int('101', 2)
parseInt("101", 2);
"hello".tr('el', 'ip') #=> "hippo"
"hello".tr('aeiou', '*') #=> "h*ll*"
"hello".tr('aeiou', 'AA*') #=> "hAll*"
ALPHABETS = list(chr(x) for x in range(ord('a'), ord('z')+1))
TRANSLATION_TABLE = str.maketrans(''.join(ALPHABETS), ''.join(reversed(ALPHABETS)))
[ch.translate(TRANSLATION_TABLE) for ch in 'aeiou']
(1..3).to_a.permutation(2).to_a
=> [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
>>> [i for i in itertools.permutations([1,2,3], 2)]
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
a = [ 4, 5, 6 ]
b = [ 7, 8, 9 ]
[1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
[1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
name = [ "Manjeet", "Nikhil", "Shambhavi", "Astha" ]
roll_no = [ 4, 1, 3, 2 ]
marks = [ 40, 50, 60, 70 ]
# using zip() to map values
mapped = zip(name, roll_no, marks)
# converting values to print as set
mapped = set(mapped)
# printing resultant values
print ("The zipped result is : ",end="")
print (mapped)
# {('Nikhil', 1, 50), ('Astha', 2, 70), ('Manjeet', 4, 40), ('Shambhavi', 3, 60)}
>>> mapped = {('Nikhil', 1, 50), ('Astha', 2, 70), ('Manjeet', 4, 40), ('Shambhavi', 3, 60)}
>>> namz, roll_noz, marksz = zip(*mapped)
>>> namz
('Manjeet', 'Astha', 'Shambhavi', 'Nikhil')
sleep 1
import time
time.sleep(2)
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
console.log("Hello");
sleep(2000).then(() => {
console.log("World!");
});
"%02d:%02d" % exact_time
format("%02d", 7) #有点不像ruby代码耶
a = 'hello'
"#{a} world"
'{:02d}:{:02d}'.format(7, 8)
'{:<30}'.format('left aligned')
# 'left aligned '
'{:>30}'.format('right aligned')
# ' right aligned'
'{:^30}'.format('centered')
# ' centered '
'{:*^30}'.format('centered') # use '*' as a fill char
# '***********centered***********'
"int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)
# 'int: 42; hex: 2a; oct: 52; bin: 101010'
# with 0x, 0o, or 0b as prefix:
"int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)
# 'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010'
'{:,}'.format(1234567890)
# '1,234,567,890'
points = 19
>>> total = 22
>>> 'Correct answers: {:.2%}'.format(points/total)
# 'Correct answers: 86.36%'
const a = "hello";
const b = `${a} world`;
console.log(b);
s = 'hello'
s.replace 'world' # => 'world'
'hello world'.replace('hello', 'world')
# 'world world'
const p =
"The quick brown fox jumps over the lazy dog. If the dog reacted, was it really lazy?";
console.log(p.replace("dog", "monkey"));
// expected output: "The quick brown fox jumps over the lazy monkey. If the dog reacted, was it really lazy?"
const regex = /Dog/i;
console.log(p.replace(regex, "ferret"));
// expected output: "The quick brown fox jumps over the lazy ferret. If the dog reacted, was it really lazy?"
import numpy
a = numpy.arange(12)
# array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
a.shape
# (12,)
a.shape = 3,4
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
a[2]
# array([ 8, 9, 10, 11])
a[2, 1]
# 9
a[:, 1]
# array([1, 5, 9])
a.transpose()
# array([[ 0, 4, 8],
# [ 1, 5, 9],
# [ 2, 6, 10],
# [ 3, 7, 11]])
lsof -i -n -P | grep 3080
nc -zvt smtp.gmail.com 654
telnet smtp.gmail.com 654
require 'socket'
port_is_open = Socket.tcp(host, port, connect_timeout: 5) { true } rescue false
# non-blocking
require 'socket'
TIMEOUT = 2
def scan_port(port)
socket = Socket.new(:INET, :STREAM)
remote_addr = Socket.sockaddr_in(port, 'www.example.com')
begin
socket.connect_nonblock(remote_addr)
rescue Errno::EINPROGRESS
end
_, sockets, _ = IO.select(nil, [socket], nil, TIMEOUT)
if sockets
p "Port #{port} is open"
else
# Port is closed
end
end
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex(('127.0.0.1',80))
if result == 0:
print "Port is open"
else:
print "Port is not open"
sock.close()
字符串字面量是切片,但是切片的时候要小心,因为不一定刚好切在字符的后面。
let s: &str = "Hello, world!"; // 字符串切片
let s = String::from("hello,world!"); // 字符串
字符串无法索引,原因是s1
实际上是字节数组,对于双字节的字符,拆开索引没有任何意义。
let s1 = String::from("hello");
let h = s1[0]; // 会报错
Push
let mut s = String::from("Hello ");
s.push('r');
println!("追加字符 push() -> {}", s);
s.push_str("ust!");
println!("追加字符串 push_str() -> {}", s);
Insert
fn main() {
let mut s = String::from("Hello rust!");
s.insert(5, ',');
println!("插入字符 insert() -> {}", s);
s.insert_str(6, " I like");
println!("插入字符串 insert_str() -> {}", s);
}
Replace
fn main() {
let string_replace = String::from("I like rust. Learning rust is my favorite!");
let new_string_replace = string_replace.replace("rust", "RUST");
dbg!(new_string_replace);
}
Pop
fn main() {
let mut string_pop = String::from("rust pop 中文!");
let p1 = string_pop.pop();
let p2 = string_pop.pop();
dbg!(p1);
dbg!(p2);
dbg!(string_pop);
}
Remove
fn main() {
let mut string_remove = String::from("测试remove方法");
println!(
"string_remove 占 {} 个字节",
std::mem::size_of_val(string_remove.as_str())
);
// 删除第一个汉字
string_remove.remove(0);
// 下面代码会发生错误
// string_remove.remove(1);
// 直接删除第二个汉字
// string_remove.remove(3);
dbg!(string_remove);
}
Truncate
fn main() {
let mut string_truncate = String::from("测试truncate");
string_truncate.truncate(3);
dbg!(string_truncate); // 测
}
Clear
fn main() {
let mut string_clear = String::from("string clear");
string_clear.clear();
dbg!(string_clear);
}
Concatenate
+
和 +=
之后必须是 &str
类型。原因是背后实际调用的是add
方法:fn add(self, s: &str) -> String
。
fn main() {
let string_append = String::from("hello ");
let string_rust = String::from("rust");
// &string_rust会自动解引用为&str
let result = string_append + &string_rust;
let mut result = result + "!";
result += "!!!";
println!("连接字符串 + -> {}", result);
}
Format
fn main() {
let s1 = "hello";
let s2 = String::from("rust");
let s = format!("{} {}!", s1, s2);
println!("{}", s);
}
#![allow(unused)]
fn main() {
println!("Hello"); // => "Hello"
println!("Hello, {}!", "world"); // => "Hello, world!"
println!("The number is {}", 1); // => "The number is 1"
println!("{:?}", (3, 4)); // => "(3, 4)"
println!("{value}", value=4); // => "4"
println!("{} {}", 1, 2); // => "1 2"
println!("{:04}", 42); // => "0042" with leading zeros
}
转义
fn main() {
println!("{}", "hello \\x52\\x75\\x73\\x74");
let raw_str = r"Escapes don't work here: \x3F \u{211D}";
println!("{}", raw_str);
// 如果字符串包含双引号,可以在开头和结尾加 #
let quotes = r#"And then I said: "There is no escape!""#;
println!("{}", quotes);
// 如果还是有歧义,可以继续增加,没有限制
let longer_delimiter = r###"A string with "# in it. And even "##!"###;
println!("{}", longer_delimiter);
}
单引号只能够是字符,双引号是字符串
'中'
"中国人"
'abc'.bytes
'abc'.bytes()
浅拷贝只发生在栈上,因此性能很高。 任何基本类型的组合可以 Copy ,不需要分配内存或某种形式资源的类型是可以 Copy 的。
所有整数类型,比如 u32。
布尔类型,bool,它的值是 true 和 false。
所有浮点数类型,比如 f64。
字符类型,char。
元组,当且仅当其包含的类型也都是 Copy 的时候。比如,(i32, i32) 是 Copy 的,但 (i32, String) 就不是。
不可变引用 &T ,例如转移所有权中的最后一个例子,但是注意: 可变引用 &mut T 是不可以 Copy 的
深拷贝
Rust 永远也不会自动创建数据的 “深拷贝”。除非显式的用clone()
方法。
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
}
socat TCP-LISTEN:3309,fork,reuseaddr TCP:mysql:3306