紅袖添香,絕代妖嬈,Ruby語言基礎入門教程之Ruby3基礎數據類型(data types)EP02

来源:https://www.cnblogs.com/v3ucn/archive/2022/12/24/16994708.html
-Advertisement-
Play Games

Ruby是強類型動態語言,即Ruby中一旦某一個對象被定義類型,如果不通過強制轉換操作,那麼它永遠就是該數據類型,並且只有在Ruby解釋器運行時才會檢測對象數據類型,它的一切皆為對象(包括 nil 值對象),可以通過調用內置class屬性來獲取該對象的具體數據類型。對於 Ruby 而言,所有類型都繼 ...


Ruby是強類型動態語言,即Ruby中一旦某一個對象被定義類型,如果不通過強制轉換操作,那麼它永遠就是該數據類型,並且只有在Ruby解釋器運行時才會檢測對象數據類型,它的一切皆為對象(包括 nil 值對象),可以通過調用內置class屬性來獲取該對象的具體數據類型。對於 Ruby 而言,所有類型都繼承自 Object 類(根類為 BasicObject)。

數字(Numeric)

數字是最基本的數據類型之一,Ruby 中包含五種內置數字類型類: Numeric, Integer, Float, Fixnum 和 Bignum, 另外標準庫中還提供了三種數字類型:Complex, BigDecimal, Rational. 除 Numeric 類外其他數字類型類都繼承自 Numeric。

irb(main):005:0> 100.class  
=> Integer

irb(main):004:0> Integer.superclass  
=> Numeric 

31位以內的整數為 Fixnum, 超過31位的數為Bignum, Bignum 沒有位數限制,可以理解為長整形。

Ruby3支持基本的數學運算符(+, -, *, /),及取餘(%), 求指數(**),等。

所有數字對象為不可變對象,因此 Ruby中沒有自增和自減操作符(++, –):

irb(main):006:0> x = 4/2       
=> 2  
irb(main):007:0> y = 6.0/2     
=> 3.0  
irb(main):008:0> x**2        
=> 4  
irb(main):009:0> x**-1         
=> (1/2)  
irb(main):010:0> x**(1/2.0)    
irb(main):011:0> x**(1/3)  
=> 1  
irb(main):012:0> x  
=> 2

在Ruby中,一元運算符+=、 -=、 *=等其它類似的操作,和對應的二元運算x = x + y是完全等價的,都會創建新的對象x。其它語言中,可能一元操作符是原處修改的,對應的二元運算是非原處修改的,所以其它語言中使用一元運算方式效率可能會稍高一些,但Ruby中是等價的,所以說變了,一元運算符在Ruby中的作用僅僅是減少代碼量,而並非有性能優化的空間。

對於浮點數來講,Ruby提供了BigDecimal類來解決精度丟失問題,使用該類可以按實際值運算,但效率上不占優勢:

irb(main):013:0> require 'bigdecimal'  
irb(main):014:0> BigDecimal('0.2') - BigDecimal('0.1') === BigDecimal('0.1')  
=> true

字元串(String)

普通字元串對象通常以雙引號的形式聲明,可轉義字元,單引號原樣輸出不轉義,字元串還可以包含變數或表達式(內嵌 #{ expr }):

irb(main):017:0> "360 degrees = #{2*Math::PI} radians"  
=> "360 degrees = 6.283185307179586 radians"

註意#{ expr }方式需要雙引號引用。

也像Python那樣可以使用類似通配符的方式格式化輸出:

irb(main):022:0> "%s: %f" % ["pi", Math::PI]  
=> "pi: 3.141593"

和其他語言不同的是,Ruby3中的字元串是可變對象:

irb(main):028:0> ss = "123"  
=> "123"  
irb(main):029:0> ss[0]  
=> "1"  
irb(main):030:0> ss[0] = "2"  
=> "2"  
irb(main):031:0> ss  
=> "223"

也就是說,如果我們定義了一個字元串,可以隨時通過下標對字元串中的字元進行修改,而Python或者Golang中的字元串是不可變對象,所以只能通過重新賦值的方式進行修改。

常用的字元串方法:

# 獲取字元串長度  
"Hello".length #=> 5  
"Hello World!".length #=> 12  
  
# 判斷字元串是否為空  
"Hello".empty? #=> false  
"!".empty?     #=> false  
" ".empty?     #=> false  
"".empty?      #=> true  
  
# 檢索字元數量  
"HELLO".count('L') #=> 2  
"HELLO WORLD!".count('LO') #=> 1  
  
# 插入字元串  
"Hello".insert(3, "hi5") #=> Helhi5lo # "hi5" is inserted into the string right before the second 'l' which is at index 3  
  
# 轉大寫  
"Hello".upcase #=> HELLO  
  
# 轉小寫  
"Hello".downcase #=> hello  
  
# 交換大小寫  
"hELLO wORLD".swapcase #=> Hello World  
  
# 字元串翻轉  
"Hello World!".reverse #=> "!dlroW olleH"  
  
# 字元串切割數組  
"Hello, how are you?".split #=> ["Hello,", "how", "are", "you?"]  
  
# 字元刪除  
name = "Batman"  
name.chop  
name == "Batma" #=> false  
  
# 清除空格  
"  Hello  ".strip #=> Hello  
  
# 強轉整形  
"15".to_i #=> 15 # integer  
  
# 字元串拼接  
  
"15" + "15" #=> "1515" # string  
  
"15" << "15" #=> "1515" # string  
  
"15".concat "15" #=> "1515" # string  
  
# 獲取字元索引  
"information".index('o') #=> 3  
"information".index('mat') #=> 5  
"information".index(/[abc]/) #=> 6  
"information".index('o', 5) #=> 9  
"information".index('z') #=> nil

可以看到,全部由字元串內置屬性完成,並不需要外部方法的參與。

與此同時,還可以通過對象的的frozen?屬性判斷類型是否可變。

irb(main):035:0> "123".frozen?  
=> false  
irb(main):036:0> 3.frozen?  
=> true

返回true為不可變對象,而false則代表可變。

符號(symbol)

符號(symbol)和字元串很相似,符號也是對象,一般作為名稱標簽來使用,用來表示變數等對象的名稱,另外符號和字元串可以相互轉換。

聲明符號:

#聲明symbol對象  
:test1  
:'test'

其實就是字元串前面加個冒號: 就是符號。

字元串和符號區別:

#可以通過object_id方法來獲得一個對象的標識符  
'test1'.object_id  
=>70201737198340   
'test1'.object_id  
=>70201752605900  
'test1'.object_id  
=>70201752351880   
  
:test2.object_id  
=>8869148   
:test2.object_id  
=>8869148   
:'test2'.object_id  
=>8869148

在Ruby3中每一個對象都有唯一對象標識符,也可以理解為記憶體地址標識,每個字元串對象都是不同的,即使它們包含了相同的字元串內容,而對於符號對象,相同的字元串內容則只會指向唯一確定的一個符號對象,這樣實際上節約了記憶體,減少了性能損耗。

符號不可以像其他變數一樣對它進行賦值運算。比如這樣的寫法是錯誤的:myname = "test"。 相反符號可以作為值賦給其他變數比如mystring = :myname。

所有符號對象存放在 Ruby內部的符號表中,可以通過類方法 Symbol.all_symbols 得到當前 Ruby 程式中定義的所有 Symbol 對象,該方法返回一個 Symbol 對象數組。

符號與字元串相互轉換:

var1 = "test".to_sym #=>:test  
  
var1 = :test.to_s #=>"test"

一般情況下,符號作為哈希的key進行取值操作,這樣效率和性能更高:

H = Hash[:"a" => 100, :"b" => 200]  
puts H[:a]

程式返回:

100

因為 Ruby3對每一次字元串引用都會生成一個字元串對象,累積下來這個開銷是相當大的。

需要註意的是,符號是不可變對象。

哈希(Hash)

哈希是一種非常有用且廣泛使用的複合容器對象,可用於存儲其他對象。我們通過鍵(key)來查找哈希中的值(value)。好比我們有一個牛津詞典,我們通過查找“hello的單詞來找到中文意思"你好",此時,“hello“就是作為鍵,而“你好”就是值。

聲明哈希:

H = {}

可以單獨對key和value進行賦值操作:

H[:a] = "123"  
  
puts H[:a]

也可以通過使用=>將鍵分配給值來創建哈希,用逗號分隔多個鍵值對,並用花括弧將整個內容括起來:

H = { "one" => "1", "two" => "2", "three" => "3" }  
  
puts H

直接通過key就可以進行取值、修改等操作:

puts H["one"]

當我們查找的鍵沒有對應內容時,會返回一個nil。

也可以使用fetch方法,他和[]方法一樣都可以查找某一個鍵的值,但是如果鍵對應的值不存在,會拋出異常。

哈希可以進行合併操作:

a = { "one" => "eins" }  
b = { "two" => "zwei" }  
puts a.merge(b)  
puts a

通過keys方法列印所有的鍵:

H = {}  
  
H[:a] = "123"  
  
puts H.keys()

也可以通過values返回一個帶有哈希所有值的數組:

H = {}  
  
H[:a] = "123"  
  
H["123"] = "123"  
  
puts H.values()

判斷哈希是否為空:

{}.empty?  
  
# ---- 輸出結果 ----  
true

也可以使用size或者length方法,判斷哈希的大小是否為0:

dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" }  
puts dictionary.size == 0  
puts dictionary.length == 0  
  
# ---- 輸出結果 ----  
false  
false

通過delete方法刪除鍵值對:

dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" }  
dictionary.delete("one")  
puts dictionary  
  
# ---- 輸出結果 ----  
{"two"=>"zwei", "three"=>"drei"}

需要註意的是,哈希是可變對象:

irb(main):041:0> {}.frozen?  
=> false

數組(Array)

數組是一個包含許多元素的對象。這些元素可以是變數(例如 字元串,數字,哈希等),甚至可以是其他對象(包括構成多維數組的其他數組)。定義中索引指的是數組元素中的一個序號,它從0開始,每個索引對應一個元素。說白了,就是一個內部元素記憶體地址連續的線性結構。

聲明數組:

A = []

創建字元串數組:

> %w{ cat dog monkey }  
=> ["cat", "dog", "monkey"]

創建符號數組:

> %i{ cat dog monkey }  
=> [:cat, :dog, :monkey]

判斷數組是否為空:

# 定義一個空數組  
> days_of_week = []  
=> []  
  
days_of_week.empty?  
=> true

也可以使用length或者size:

> days_of_week.length == 0  
=> true  
  
> days_of_week.size == 0  
=> true

通過索引訪問數組元素:

# 定義一個數組  
> days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]  
=> [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]  
  
> days_of_week[0]  
=> "Mon"  
  
> days_of_week[1]  
=> "Tues"

使用數組的first和last方法訪問首個和末尾元素:

> days_of_week.first  
=> "Mon"  
  
> days_of_week.last  
=> "Sun"

通過index返回元素下標:

# 定義一個數組  
> days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]  
=> [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]  
  
> days_of_week.index("Wed")  
=> 2

提取子元素:

# 定義一個數組  
> days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]  
=> [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]  
  
> days_of_week[1, 3]  
=> ["Tues", "Wed", "Thu"]

也可以針對數組指定範圍:

> days_of_week[1..3]  
=> ["Tues", "Wed", "Thu"]

合併數組:

days1 = ["Mon", "Tue", "Wed"]  
days2 = ["Thu", "Fri", "Sat", "Sun"]  
days = days1 + days2  
  
=> ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]

使用<<將元素動態附加到現有數組:

days1 = ["Mon", "Tue", "Wed"]  
days1 << "Thu" << "Fri" << "Sat" << "Sun"  
  
=> ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]

數組的交集 &:

operating_systems = ["Fedora", "SuSE", "RHEL", "Windows", "MacOS"]  
  
linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"]  
  
operating_systems & linux_systems  
=> ["Fedora", "SuSE", "RHEL"]

數組的差集 -

operating_systems = ["Fedora", "SuSE", "RHEL", "Windows", "MacOS"]  
  
linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"]  
  
operating_systems  - linux_systems  
  
linux_systems - operating_systems

數組的並集 |

operating_systems = ["Fedora", "SuSE", "RHEL", "Windows", "MacOS"]  
  
linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"]  
  
operating_systems | linux_systems  
=> ["Fedora", "SuSE", "RHEL", "Windows", "MacOS", "PCLinuxOS", "Ubuntu"]

數組刪除重覆元素:

linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora", "RHEL", "SuSE"]  
  
linux_systems.uniq  
=> ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"]

向數組中增加或減少元素(push和pop)

colors = ["red", "green", "blue"]  
=> ["red", "green", "blue"]  
  
colors.push "indigo"  
=> ["red", "green", "blue", "indigo"]  
  
colors.push "violet"  
=> ["red", "green", "blue", "indigo", "violet"]  
  
colors.pop  
=> "violet"  
  
colors.pop  
=> "indigo"

基於先進後出原則。

數組插入元素:

colors = ["red", "green", "blue"]  
=> ["red", "green", "blue"]  
  
colors.insert( 1, "orange" )  
=> ["red", "orange", "green", "blue"]

基於下標來刪除元素:

colors = ["red", "green", "blue"]  
=> ["red", "green", "blue"]  
  
colors.delete_at(1)  
=> "green"  
  
colors  
=> ["red", "blue"]

基於元素內容來刪除:

colors = ["red", "green", "blue"]  
=> ["red", "green", "blue"]  
  
colors.delete("red")  
=> "red"  
  
colors  
=> ["green", "blue"]

最後是排序:

numbers = [1, 4, 6, 7, 3, 2, 5]  
=> [1, 4, 6, 7, 3, 2, 5]  
  
numbers.sort  
=> [1, 2, 3, 4, 5, 6, 7]

布爾和Nil

true 和 false 為兩個布爾型的值,與其他語言理解有差別的是,除了 false 和 nil 外,其他值都為 true:

!true   # false  
!false  # true  
!nil    # true  
!0      # false  
![]     # false

nil 表示空值對象。對於值判空操作可調用 nil? 方法:

false.nil?   # false  
nil.nil?    # true

需要註意的是,Ruby3中的nil是一個對象,表示沒有任何東西的對象,而不是沒有對象。nil與nil的比較無論是==還是eql?都返回true。

結語

字元、數字、布爾是不可變對象,而字元串、數組、哈希是可變對象,Ruby3中所有不可變對象的多個同值對象,都會指向同一個對象的記憶體地址。例如所有的1數值都是同一個對象,所有的nil、布爾值相同的字元對象也都是指向同一個對象,這也導致了Ruby3中不支持++或者--這樣的操作,因為這要求在記憶體地址中指向的原對象進行增減操作,造成對象引用混亂的現象。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Mysql 作為互聯網中非常熱門的資料庫,其底層的存儲引擎和數據檢索引擎的設計非常重要,尤其是 Mysql 數據的存儲形式以及索引的設計,決定了 Mysql 整體的數據檢索性能。 ...
  • Web 標準 & W3C 規範 引用 最全面的前端筆記來啦,包含了入門到入行的筆記,還支持實時效果預覽。小伙伴們不需要在花時間去寫筆記,或者是去網上找筆記了。面試高頻提問和你想要的筆記都幫你寫好了。支持移動端和PC端閱讀,深色和淺色模式。 原文鏈接:https://note.noxussj.top/ ...
  • 在JS中,類是後來才出的概念,早期創造對象的方式是new Function()調用構造函數創建函數對象; 而現在,可以使用new className()構造方法來創建類對象了; 所以在很多方面,類的使用方式,很像函數的使用方式: 但是類跟函數,還是有本質區別的,這在原型那裡已經說過,不再贅述; 如何 ...
  • 好家伙,本篇為《JS高級程式設計》第八章“對象、類與面向對象編程”學習筆記 1.工廠模式 工廠模式是另外一種關註對象創建概念的創建模式。 它的領域中同其它模式的不同之處在於它並沒有明確要求我們使用一個構造器。 取而代之,一個工廠能提供一個創建對象的公共介面,我們可以在其中指定我們希望被創建的工廠對象 ...
  • ​ 目錄 1.前言 2.目標與效果展示 3.下載OpenCV圖形識別庫 4.下載python支持的v2模塊 5.圖片素材 6.代碼 1.前言 ​ 編輯 Merry Christmas!今天是2022年12月24日,今晚是平安夜在這裡提前祝大家聖誕節快樂! 大家可能對@官方微信給自己的頭像加上一頂聖誕 ...
  • 摘要:教你如何用java實現每日給女友微信發送早安等微信信息。 本文分享自華為雲社區《java實現每日給女友微信發送早安等微信信息》,作者:穆雄雄 。 前言 據說這個功能最近在抖音上很火,我沒有抖音,沒有看到。 但是我在網上看了,相關案例確實很多,但是大家都是藉助於了微信服務號,在我看來,效果很不佳 ...
  • 一、選題的背景 (1)為什麼要選擇此選題? 樂高是一個很受歡迎的玩具積木品牌,它們通常是成套出售的,用來製作特定的物品,每一套都包含許多不同形狀、大小和顏色的零件。它是一個有趣的數據集合,它包含了多年來集合的綜合列表,以及每個集合包含的部分數。提供了許多可供探索的空間,特別是因為“集合”文件包含了集 ...
  • C++ 基礎3 typedef 為現有類型創建一個新名字 主要有以下幾種形式: 為基本數據類型定義別名 為指針定義別名 為自定義數據類型定義別名 為數組定義別名 聲明函數 定義新名稱為了簡化一些複雜的數據類型,以方便使用 為基本數據類型定義名稱 語法typedef 舊類型 新名字 例如: typed ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...