{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/python_with_Birds.gif)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(ch3-1)=\n", "# Tuples (ทูเพิล)\n", "\n", "ในบทนี้ คุณจะได้เรียนรู้เกี่ยวกับ Tuple ในภาษาไพธอน และทำความรู้จักกับ Tuple ว่าคืออะไร เรียนรู้วิธีการประกาศและการใช้งาน Tuple นอกจากนี้ ยังจะอธิบายถึงการใช้งานเมธอดและฟังก์ชันต่างๆ ของ Tuple\n", "\n", "Ref: \n", "\n", "* https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences\n", "* https://realpython.com/python-lists-tuples\n", "* https://realpython.com/python-sort" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ชุดข้อมูล (Dataset)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ Dataset หรือที่เรียกว่า \"ชุดข้อมูล/เซ็ทของข้อมูล\" หมายถึง ข้อมูลที่ถูกจัดให้เป็นกลุ่มถูกต้องตามลักษณะโครงสร้างข้อมูล สามารถที่จะนำไปใช้ประมวลผลได้ บางครั้งใช้ในความหมายเหมือน \"แฟ้มข้อมูล\"\n", "\n", "$\\qquad$ สมมุติว่าคุณได้รับชุดข้อมูล (Dataset) เพลงซึ่งเป็นข้อมูลของเพลงฮิตในแต่ละปี (2010~2019) ในรูปแบบของตาราง โดยแต่ละแถว (row) ในตารางเป็นข้อมูลของเพลงแต่ละเพลง และแต่ละคอลัมน์ (column) มีข้อมูลดังต่อไปนี้\n", "\n", "* **artist** - ชื่อศิลปิน (นักร้อง วงดนตรี)\n", "* **genre** คือแนวเพลงหรือประเภทของแนวดนตรี เช่น pop, pop dance, rock\n", "* **year** คือปี (ค.ศ) ของเพลงที่อยู่ในบิลบอร์ด (Billboard)\n", "* **bpm** (Beats.Per.Minute: Tempo) คือจังหวะเร็วช้าขนาดไหน หน่วยเป็น bpm \n", "* **nrgy** (Energy) คือพลังหรือความพุ่งของเพลง\n", "* **dnce** (Danceability) คือความดิ้น หรือความน่าเต้นของเพลง\n", "* **dB** (Loudness) คือระดับความดังในหน่วย decibel \n", "* **live** (Liveness) คือระดับของการแสดงสด (Live) ของเพลง \n", "* **val** (Valence) คือระดับความเป็นเชิงบวก (positive) ในเพลง (ค่าต่ำ: เศร้า-หดหู่-โกรธ,ค่าสูง: มีความสุข-ให้กำลังใจ)\n", "* **dur** (Length) - คือความยาว (ระยะเวลา) ของเพลง/ดนตรี\n", "* **acous** (Acousticness) คือความ “acoustic” ของเพลง\n", "* **spch** (Speechiness) คือปริมาณของคำพูดหรือเนื้อร้อง\n", "* **pop** (Popularity) คือระดับความนิยม ยิ่งค่าสูงเท่าไหร่ ยิ่งเป็นที่นิยม\n", "\n", "
\n", "
\n", "\n", "ชุดข้อมูลที่ได้รับอยู่ในรูปตาราง (Format CSV)\n", "\n", "(Source: spotifycharts.com, kaggle.com)\n", "\n", "| # | title | artist | genre | year | bpm | nrgy | dnce | dB | live | val | dur | acous | spch | pop |\n", "|:--|:------|:-------|:------|:-----|:----|:-----|:-----|:---|:-----|:----|:----|:-----|:-----|:----|\n", "|1 |Memories [$\\triangleright$](https://www.youtube.com/watch?v=SlPhMPnQ58k) |Maroon 5 |pop |2019|91 |32 |76 |-7 |8 |57 |189|84 |5 |99 |\n", "|2 |Lose You To Love Me [$\\triangleright$](https://www.youtube.com/watch?v=zlJDTxahav0) |Selena Gomez |dance pop |2019|102|34 |51 |-9 |21 |9 |206|58 |4 |97 |\n", "|3 |Someone You Loved [$\\triangleright$](https://www.youtube.com/watch?v=zABLecsR5UE) |Lewis Capaldi |pop |2019|110|41 |50 |-6 |11 |45 |182|75 |3 |96 |\n", "|4 |Senorita [$\\triangleright$](https://www.youtube.com/watch?v=Pkh8UtuejGw) |Shawn Mendes |canadian pop |2019|117|54 |76 |-6 |9 |75 |191|4 |3 |95 |\n", "|5 |How Do You Sleep? [$\\triangleright$](https://www.youtube.com/watch?v=PmYypVozQb4) |Sam Smith |pop |2019|111|68 |48 |-5 |8 |35 |202|15 |9 |93 |\n", "|6 |South of the Border (feat. Camila Cabello & Cardi B) |Ed Sheeran |pop |2019|98 |62 |86 |-6 |9 |67 |204|15 |8 |92 |\n", "|7 |Trampoline (with ZAYN) |SHAED |electropop |2019|127|46 |62 |-6 |14 |50 |184|56 |3 |92 |\n", "|8 |Happier |Marshmello |brostep |2019|100|79 |69 |-3 |17 |67 |214|19 |5 |90 |\n", "|9 |Truth Hurts |Lizzo |escape room |2019|158|62 |72 |-3 |12 |41 |173|11 |11 |90 |\n", "|10 |Good as Hell (feat. Ariana Grande) - Remix |Lizzo |escape room |2019|96 |89 |67 |-3 |74 |48 |159|30 |6 |90 |\n", "|11 |Underneath the Tree |Kelly Clarkson |dance pop |2013|160|81 |51 |-5 |21 |69 |230|0 |5 |88 |\n", "|12 |Higher Love |Kygo |edm |2019|104|68 |69 |-7 |10 |40 |228|2 |3 |88 |\n", "|13 |Shape of You |Ed Sheeran |pop |2017|96 |65 |83 |-3 |9 |93 |234|58 |8 |87 |\n", "|14 |Only Human |Jonas Brothers |boy band |2019|94 |50 |80 |-6 |6 |87 |183|11 |7 |87 |\n", "|15 |All of Me |John Legend |neo mellow |2014|120|26 |42 |-7 |13 |33 |270|92 |3 |86 |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ออบเจกต์ประเภท Collections และประเภทลำดับ (Sequences) \n", "\n", "โครงสร้างข้อมูลในภาษาไพธอนสามารถแบ่งออกเป็น 2 ประเภทใหญ่ๆ คือ\n", "* ออบเจกต์ประเภท Collections\n", "* ออบเจกต์ประเภทลำดับ (Sequences)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ **ออบเจกต์ประเภท Collections (หรือ Container datatype)** เป็นออบเจกต์ที่เก็บข้อมูลหลายๆ ข้อมูลรวมกันเป็นชุดข้อมูลเดียวกัน และใช้ชื่อตัวแปรตัวเดียวกัน โดยในภาษาไพธอน มีชนิดของข้อมูลที่เป็นประเภท Collections พื้นฐานอยู่ 4 ชนิด ได้แก่ Tuple, List, Set และ Dictionary\n", "\n", "ตัวอย่างของออบเจกต์ประเภท Collections โดยเรียงจาก Tuple, List, Set และ Dictionary ตามลำดับ\n", "\n", "```\n", "coordinates = (1, 9, 5)\n", "languages = [\"Python\", \"C\", \"C++\", \"Java\", \"Perl\"]\n", "colors = {'red', 'blue', 'white'}\n", "item_counts = {'computers': 2, 'headphones': 4, 'cellphones': 3}\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ **ออบเจกต์ประเภทลำดับ (Sequence หรือ sequential datatype)** เป็นออบเจกต์พื้นฐานที่ใช้เก็บชุดข้อมูล (เซ็ทของข้อมูล) ที่มีการจัดเรียงตามลำดับ (Sequence) \n", "ในภาษา Python มีออบเจกต์ประเภทลำดับอยู่มากมายหลากหลายชนิด เช่น str, tuple, list และ range ออบเจกต์เหล่านี้สามารถเก็บข้อมูลได้มากกว่าหนึ่งตัวโดยมีการจัดเรียงข้อมูลตามลำดับ และสามารถเข้าถึงข้อมูลภายแต่ละตัวได้โดยใช้เลขดัชนี (index)\n", "\n", "ตัวอย่างของออบเจกต์ประเภทลำดับ โดยเรียงจาก str, tuple, list และ range ตามลำดับ\n", "```\n", "greetings = \"Hey, guys!\"\n", "coordinates = (1, 9, 5)\n", "languages = [\"Python\", \"C\", \"C++\", \"Java\", \"Perl\"]\n", "range(0,10)\n", "\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tuples (ทูเพิล) คือ?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ ชนิดของข้อมูลในภาษา Python ที่เราได้เรียนรู้ที่ผ่านมา \n", "ไม่ว่าจะเป็น float ใช้สำหรับจำนวนจริง, int ใช้สำหรับจำนวนเต็ม, str ใช้สำหรับสตริงหรือข้อความ และ bool ใช้สำหรับข้อมูลแบบตรรกะ (True, False) ข้อมูลที่มีชนิดต่างๆ กันเหล่านี้สามารถทำให้อยู่ในรูปของชุดข้อมูล หรือเซ็ทของข้อมูล (Dataset) เดียวกันที่เรียกว่า \"Tuple\" (ออกเสียงว่า \"ทูเพิล\") ได้\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ Tuple เป็นหนึ่งในออบเจกต์ประเภท Collections และยังเป็นออบเจกต์ประเภทลำดับ (Sequential datatype) อีกด้วย กล่าวคือ มันสามารถเก็บข้อมูลได้หลายชนิดหลายค่าในตัวแปรตัวเดียว (ดังแสดงในรูปด้านล่าง)โดยมีการจัดเรียงลำดับของข้อมูล (เรียงลำดับดังแสดงในรูป) **แต่จะไม่สามารถเปลี่ยนแปลง (แก้ไข ลบหรือเพิ่ม) หลังจากที่ถูกสร้างขึ้นมาแล้ว (Tuple เป็นข้อมูลชนิด Immutable เช่นเดียวกับสตริง)** และข้อมูลที่เก็บยังสามารถเป็นข้อมูลที่มีชนิดแตกต่างกันได้อีกด้วย (Heterogeneous data) (Tuple ในรูปเก็บข้อมูลชนิด str int และ float)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesType.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## การสร้าง Tuple\n", "\n", "$\\qquad$ ข้อมูลแบบ Tuple จะถูกเขียนอยู่ในเครื่องหมายวงเล็บ **( )**
\n", "\n", "\n", "เราลองมาสร้างตัวแปรชนิด Tuple ที่มีชุดข้อมูลที่ประกอบไปด้วย สตริง (str), จำนวนเต็ม (int) และ จำนวนจริง (float) และใช้งาน Tuple ในเบื้องต้นกัน!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{note} **เครื่องหมายวงเล็บในภาษาไพธอน (มีกี่แบบและใช้ต่างกันอย่างไร?)**\n", "\n", "* เครื่องหมายวงเล็บสี่เหลี่ยม (สแควร์แบร็กเกต; Square bracket)) `[]` ใช้สร้าง Lists ใช้กับเลขดัชนี (indexing) ใช้ค้นหา key ในข้อมูลชนิด Dic และใช้ในการตัด (slicing) หรือใช้เป็นโอเปอร์เรเตอร์ในคลาส เช่น\n", "\n", ">>> สร้าง Lists: [], [1, 2, 3], [i**2 for i in range(5)]\n", "\n", ">>> เลขดัชนี: 'abc'[0] $\\Rightarrow$ 'a'\n", "\n", ">>> ค้นหา key: {0: 10}[0] $\\Rightarrow$ 10\n", "\n", ">>> การตัด: 'abc'[:2] $\\Rightarrow$ 'ab'\n", "\n", "* เครื่องหมายวงเล็บ (ราวด์แบร็กเกต; Round brackets, Parentheses) '()' ใช้สร้าง Tuples ใช้จัดลำดับการประมวลผล ใช้เรียกฟังก์ชันหรือเมธอด หรือใช้เป็นโอเปอร์เรเตอร์ในคลาส เป็นต้น เช่น\n", "\n", ">>> สร้าง Tuples: (), (1, 2, 3)\n", "\n", ">>> จัดลำดับการประมวลผล: (5-1)**2\n", "\n", ">>> เรียกฟังก์ชันหรือเมธอด:: print(), int(), range(5), '1 2 3'.split(' ')\n", "\n", "* เครื่องหมายวงเล็บปีกา (เคิร์ลลี่แบร็กเกต; curly brackets) `{}` ใช้สร้าง Dictionaries และ Sets ใช้จัดรูปแบบของสตริง (เมธอด ```str.format( )``` และการเขียนในรูปแบบ f-string) \n", "\n", ">>> สร้าง Dicts: {}, {0: 10}, {i: i**2 for i in range(5)}\n", "\n", ">>> สร้าง Sets: {0}, {i**2 for i in range(5)}\n", ">>>>>> ยกเว้น set ว่าง (ไม่มีสมาชิก; empty set): set()\n", ">>> จัดรูปแบบของสตริงเพื่อแทนที่\n", ">>>>>> รูปแบบ f-strings: f'{total_hour}'\n", ">>>>>> เมธอด format(): '{x}'.format(x=total_min)\n", "\n", "* เครื่องหมายวงเล็บมุม (แองเกิลแบร็กเกต; Angle brackets, chevron) '<>' ใช้ในการแสดงชนิดของออบเจ็กต์ เช่น ฟังก์ชัน คลาส และอินสแตนซ์ของคลาส เช่น\n", "\n", ">>> ``````\n", "\n", ">>> \n", "\n", ">>> \n", "\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('dance', 10, 1.2)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# สร้างตัวแปรชนิด Tuple โดยสมาชิกใน tuple ไม่จำเป็นต้องเป็นชนิดเดียวกัน\n", "tuple1 = (\"dance\",10,1.2 )\n", "tuple1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถใชัฟังก์ชัน ```type()```ตรวจสอบชนิดของตัวแปร ```tuple1``` ได้ ซึ่งแน่นอน มันคือ **tuple**" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tuple" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ชนิดของตัวแปร tuple1 ที่สร้างขึ้น\n", "type(tuple1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ในกรณีที่สมาชิกมีแค่ตัวเดียว จะไม่เขียนแบบนี้ ```t1 = (\"dance\")``` เพราะจะกลายเป็นข้อมูลชนิด ```str``` " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "str" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t1 = (\"dance\")\n", "type(t1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "แต่ต้องเขียนคั่นด้วยเครื่องหมายจุลภาคแบบนี้แทน (แม้สมาชิกจะมีแค่ตัวเดียว ก็ต้องมีเครื่องหมายจุลภาค!)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tuple" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t1 = (\"dance\",)\n", "type(t1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "อย่างไรก็ตาม การสร้างตัวแปร tuple สามารถที่จะละเว้นวงเล็บได้\n", "แต่ยังคงต้องคั่นแต่ละค่าด้วยเครื่องหมายจุลภาค โดยไพธอนจะแพ็คค่าที่ถูกคั่นด้วยเครื่องหมายจุลภาคที่อยู่ทางขวามือของเครื่องหมาย ```=``` รวมไว้เป็น tuple โดยอัตโนมัติ\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('dance', 10, 1.2)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tuple1 = \"dance\",10,1.2 \n", "tuple1" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('dance',)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t1 = \"dance\",\n", "t1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{attention}\n", "ขอแนะนำว่า อย่าเพิ่งละวงเล็บในช่วงเริ่มต้นเขียนโปรแกรมไพธอน เพราะจะทำให้งง\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ในการกำหนดค่าให้กับตัวแปร tuple \n", "เราสามารถกำหนดค่าจากตัวแปรที่มีอยู่ก็ได้ โดยใช้เครื่องหมายวงเล็บ **()** " ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 2, 3)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x1 = 1 # กำหนดค่าให้ตัวแปร x1\n", "y1 = 2 # กำหนดค่าให้ตัวแปร y1\n", "z1 = 3 # กำหนดค่าให้ตัวแปร z1\n", "p1 = (x1, y1 ,z1) # กำหนดค่าให้ตัวแปร p1 (ซึ่งเป็น tuple) ที่ประกอบด้วยสมาชิก 1, 2 และ 3\n", "p1 # แสดง p1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "หรือจะละ ```()``` แบบนี้ก็ได้ เช่นกัน" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 2, 3)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p1 = x1, y1 ,z1 # p1 เป็น tuple ที่ประกอบด้วยสมาชิก 1, 2 และ 3\n", "p1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราเรียกการกำหนดค่าของสมาชิกหลายๆ ตัวลงในตัวแปร Tuple ตัวเดียวแบบนี้ ว่า \"การแพ็คทูเพิล\" (Tuple packing; \"แพ็ก\" ข้อมูลหลายๆ ตัวให้เป็น Tuple) \n", "\n", "ในทางกลับกัน ไพธอนก็มี \"การอันแพ็คทูเพิล\" (Tuple unpacking) ซึ่งเป็นการกระจายหรือการแตกข้อมูลใน Tuple ลงในตัวแปรหลายตัวหลายๆ ตัวพร้อม ๆ กัน" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(x2,y2,z2) is (6,7,8)\n" ] } ], "source": [ "p2 = (6,7,8) # สร้างทูเพิล p2 ที่ประกอบด้วย 3 สมาชิก\n", "x2, y2, z2 = p2 # แตกสมาชิกของ p2 เพื่อกำหนดค่าลงในตัวแปร 3 ตัว x2, y2 และ z2 ตามลำดับ\n", "print(\"(x2,y2,z2) is ({},{},{})\".format(x2, y2, z2)) # แสดงค่าของตัวแปร x2, y2 และ z2 ตามลำดับ" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$$ $$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เช่นเดียวกับข้อมูลชนิดสตริง เราสามารถเข้าถึงสมาชิกที่อยู่ใน Tuple ได้โดยใช้ชื่อตัวแปรตามด้วยเลขดัชนีในวงเล็บสี่เหลี่ยม ```[ ]```" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'dance'" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tuple1[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "สิ่งที่เหมือนกับข้อมูลชนิดสตริงอีกอย่างคือ เราก็ไม่สามารถเปลี่ยนแปลงหรือแก้ไขสมาชิกของ Tuple ได้ " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'tuple' object does not support item assignment", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn [11], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mtuple1\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mrock\u001b[39m\u001b[38;5;124m'\u001b[39m\n", "\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment" ] } ], "source": [ "tuple1[0] = 'rock'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ไพธอนจะแจ้งเตือน (TypeError) เนื่องจาก Tuple เป็นประเภทข้อมูลที่ไม่สามารถเปลี่ยนแปลงได้ (Immutable data structure) เช่นเดียวกับข้อมูลชนิดสตริง (Immutable objects: int, float, string, tuple, frozen Set)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "แต่ไม่ได้หมายความว่าเราจะเปลี่ยนค่าของตัวแปรให้เป็น tuple อื่นไม่ได้" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('dance', 10, 1.2)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tuple1 # ค่าของตัวแปร tuple1" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('rock', 10, 1.2)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tuple1 = \"rock\",10,1.2 # เปลี่บนค่าของตัวแปร tuple1 ให้เป็น tuple ใหม่\n", "tuple1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "สรุป: เราไม่สามารถเปลี่ยนแปลงสมาชิกของ tuple ได้ (เนื่องจากเป็นข้อมูล Immutable) แต่เราสามารถเปลี่ยนค่าของตัวแปรให้เป็น tuple อื่นได้" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "### เลขดัชนี (Index)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "$\\qquad$ ตารางต่อไปนี้แสดงความสัมพันธ์ระหว่างเลขดัชนีและสมาชิกที่อยู่ภายใน Tuple \n", "\n", "เราสามารถเข้าถึงสมาชิกที่อยู่ใน Tuple ได้ โดยใช้ชื่อตัวแปรตามด้วยวงเล็บเหลี่ยม [ ] ที่มีเลขดัชนี\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesIndex.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{tip}\n", "ในภาษาไพธอน เลขดัชนี (Index) จะเริ่มจาก \"0\" เสมอ\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถใช้ฟังก์ชัน ```print( )``` แสดงสมาชิกแต่ละตัวที่อยู้ใน Tuple ได้\n" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "rock\n", "10\n", "1.2\n" ] } ], "source": [ "# แสดงค่าของสมาชิกแต่ละตัวที่อยู่ในตัวแปรออกหน้าจอโดยใช้เลขดัชนี\n", "\n", "print(tuple1[0])\n", "print(tuple1[1])\n", "print(tuple1[2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถใชัฟังก์ชัน ```type( )``` ตรวจสอบสมาชิกแต่ละตัวของ Tuple ว่าเป็นข้อมูลชนิดใด\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "\n" ] } ], "source": [ "# แสดงชนิดข้อมูลของสมาชิกแต่ละตัวที่อยู่ในตัวแปรออกหน้าจอโดยใช้เลขดัชนี\n", "\n", "print(type(tuple1[0]))\n", "print(type(tuple1[1]))\n", "print(type(tuple1[2]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ถ้าเรารู้ว่าใน Tuple มีสมาชิกที่มีมีค่า ```10``` อยู่ เราสามารถหาตำแหน่ง (เลขดัชนี) ของ ```10``` ได้โดยใช้เมธอด ```index()```\n", "\n", "เมธอด ```index()``` จะส่งกลับเป็นเลขดัชนีของสมาชิกที่อยู่ใน Tuple\n", "\n", "```{note} \n", "เมธอด ```index()``` ยังสามารถใช้กับออบเจ็กต์ประเภทลำดับ (Sequence) อื่นๆ เช่น str, tuple, list, range เป็นต้น ก็ได้\n", "```" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tuple1.index(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "นอกจากนี้ เรายังสามารถใช้ดัชนีเชิงลบ (Negative index) กับ Tuple ได้เช่นกัน\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesNeg.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{tip}\n", "ดัชนีของข้อมูลตัวสุดท้ายมีค่าเป็น -1 ! (เช่นเดียวกับสตริง)\n", "```" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.2" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ดัชนีเชิงลบมักใช้ในการเข้าถึงสมาชิกตัวสุดท้าย\n", "\n", "tuple1[-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ข้อมูลตัวถัดไป และตัวถัดๆ ไป" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ใช้ดัชนีเชิงลบเข้าถึงสมาชิกตัวรองสุดท้าย\n", "\n", "tuple1[-2]" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'rock'" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ใช้ดัชนีเชิงลบเข้าถึงสมาชิกตัวตัวที่สามจากท้าย\n", "\n", "tuple1[-3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### การเชื่อม Tuple (Concatenate Tuples)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ เราสามารถเชื่อมหรือรวม Tuple เข้าด้วยกันโดยใช้โอเปอร์เรเตอร์ **```'+'```** และผลลัพธ์ที่ได้คือ Tuple ใหม่ที่รวมสมาชิกของทั้งสองเข้าด้วยกัน\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesCombine.png)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('rock', 10, 1.2, 'dance pop', 10)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# เชื่อม 2 Tuple เข้าด้วยกัน\n", "\n", "tuple2 = tuple1 + (\"dance pop\", 10)\n", "tuple2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### การตัด (Slicing) Tuple" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ เราสามารถตัด (Slicing) Tuple ได้หลายค่า ดังแสดงในรูปด้านล่าง\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesSlice1.png)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('rock', 10, 1.2)" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ตัดสมาชิกตั้งแต่ดัชนี 0 ถึงดัชนี 2\n", "\n", "tuple2[0:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesSlice2.png)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('dance pop', 10)" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ตัดสมาชิกตั้งแต่ดัชนี 3 ถึงดัชนี 4\n", "\n", "tuple2[3:5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถหาจำนวนสมาชิกทั้งหมดที่อยู่ใน Tuple ได้โดยใช้ฟังก์ชัน ```len()``` ซึ่งย่อมาจาก **len**gth" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# จำนวนสมาชิกทที่อยู่ใน Tuple\n", "\n", "len(tuple2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### การจัดเรียงข้อมูล (Sorting)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ ตัวแปร ```Ratings``` ด้านล่างนี้เป็นข้อมูลชนิด Tuple ที่มีสมาชิกเป็นเลขจำนวนเต็ม (int)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "# กำหนดตัวแปร Tuple เก็บค่าเรตติ้ง\n", "\n", "Ratings = (0, 9, 6, 5, 10, 8, 9, 6, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถจัดเรียงข้อมูลที่อยู่ใน Tuple และบันทึกค่าเป็น Tuple **ใหม่**ได้\n" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 2, 5, 6, 6, 8, 9, 9, 10]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# จัดเรียง tuple ด้วยฟังก์ชัน sorted\n", "\n", "RatingsSorted = sorted(Ratings)\n", "RatingsSorted" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ฟังก์ชัง sorted() ส่งกลับเป็นข้อมูลชนิด **List** ลองตรวจสอบชนิดของข้อมูลด้วยฟังก์ชัน ```type()```" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "list" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(RatingsSorted)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถเปลี่ยนชนิดข้อมูลจาก list ให้เป็น tuple ได้โดยใช้ฟังก์ชัน tuple()" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(0, 2, 5, 6, 6, 8, 9, 9, 10)" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tuple(RatingsSorted)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tuple ที่สมาชิกมีชนิดข้อมูลต่างชนิดกัน จะไม่สามารถเรียกฟังก์ชัน ```sorted()``` ได้ ดังตัวอย่างต่อไปนี้" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'<' not supported between instances of 'str' and 'int'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn [28], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m mixed_numbers \u001b[38;5;241m=\u001b[39m (\u001b[38;5;241m5\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;241m100\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m34\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;43msorted\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mmixed_numbers\u001b[49m\u001b[43m)\u001b[49m\n", "\u001b[0;31mTypeError\u001b[0m: '<' not supported between instances of 'str' and 'int'" ] } ], "source": [ "mixed_numbers = (5, \"1\", 100, \"34\")\n", "sorted(mixed_numbers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ไพธอนแจ้งเตือนเป็น 'TypeError' เนื่องจากมีสมาชิกบางตัวเป็นสตริง บางตัวเป็นตัวเลข ไม่เป็นชนิดเดียวกันทั้งหมด ในกรณีเราต้องทำการเปลี่ยนชนิดของข้อมูลก่อน โดยใช้ฟังก์ชันที่ชื่อเดียวกับชนิดข้อมูล แล้วจึงเรียกใช้ฟังก์ชัน ```sorted()``` จัดเรียงข้อมูล" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(5, 1, 100, 34)" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# เปลี่ยนสมาชิกทุกตัวจากชนิิด str ให้เป็นชนิด int\n", " \n", "sorted_numbers = (int(mixed_numbers[0]),)+(int(mixed_numbers[1]),)+(int(mixed_numbers[2]),)+(int(mixed_numbers[3]),)\n", "sorted_numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "หรือ อาจะเขียนโค้ดให้สั้นๆ ได้โดยใช้ comprehension" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 5, 34, 100]" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ใช้ Tuple comprehension แปลงค่าทั้งหมดให้เป็นจำนวนเต็ม\n", "sorted((int(x) for x in mixed_numbers))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "หากต้องการให้เรียงจากมากไปหาน้อย ก็สามารถทำได้โดยส่งอาร์กิวเมนต์ ```reverse=True```\n" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[100, 34, 5, 1]" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# เรียงจากมากไปหาน้อย reverse=True \n", "sorted((int(x) for x in mixed_numbers), reverse=True)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**สรุป:** ```sorted()``` เป็นฟังก์ชัฝังตัว (Built-in function) เหมือนฟังก์ชัน ```print()``` ใช้จัดเรียงข้อมูล ใช้ได้กับข้อมูลที่เป็นตัวเลขและสตริง **แต่ชนิดข้อมูลที่จัดเรียงต้องเป็นชนิดใดชนิดหนึ่งเหมือนกันทั้งหมด ผสมปนรวมกันไม่ได้!** โดยจะจัดเรียงจากน้อยไปหามาก (reverse=False เป็นค่าดีฟอลต์) และส่งกลับเป็นข้อมูลชนิด **List** ที่จัดเรียงเรียบร้อยแล้ว (หากต้องการเปลี่ยน List ให้เป็น Tuple ก็สามารถทำได้ใช้ฟังก์ชัน ```tuple()```)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{note}\n", "* ฟังก์ชัน ```tuple()``` ใช้เปลี่ยนข้อมูล (เช่น เปลี่ยน List) ให้เป็น Tuple\n", "* ฟังก์ชัน ```list()``` ใช้เปลี่ยนข้อมูล (เช่น เปลี่ยน Tuple) ให้เป็น List\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "นอกจากฟังก์ชัน ```sorted()``` แล้ว ยังมีฟังก์ชัน ```max()``` และ ```min()```" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "tup = (-70, -80, 10, 20, 30, 0, 29, -97)\n", "biggest = max(tup)\n", "smallest = min(tup)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The biggest numner: 30\n", "The smallest numner: -97\n" ] } ], "source": [ "print('The biggest numner:', biggest)\n", "print('The smallest numner:', smallest)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เช่นเดียวกับฟังก์ชัน ```sorted()``` ฟังก์ชัน ```max()``` และ ```min()``` ยังใช้กับข้อมูลชนิดสตริงก็ได้" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'ก'" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "min('กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ')" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'๙'" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "max('๐๑๒๓๔๕๖๗๘๙')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tuple ซ้อน Tuple (Nested Tuple)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ สมาชิกที่อยู่ใน Tuple สามารถเป็น Tuple หรือข้อมูลที่ซับซ้อนอื่นๆ ก็ได้ เราเรียกระบวนการนี้ว่า **'การซ้อน (nesting)'** \n", "\n", "ลองพิจารณา Tuple ที่มีสมาชิกหลากหลายชนิด (มีสมาชิกที่เป็น int, Tuple และ Nested Tuple) ต่อไปนี้\n" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "# สร้าง nested tuple\n", "\n", "NestedT =(1, 2, (\"pop\", \"rock\") ,(3,4),(\"dance\",(1,2)))" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 2, ('pop', 'rock'), (3, 4), ('dance', (1, 2)))" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "NestedT" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถเข้าถึงสมาชิกแต่ละตัวที่อยู่ใน Tuple (\"Tuple หลัก\") รวมถึงสมาชิกที่เป็น Tuple (\"Tuple สมาชิก\") ได้โดยใช้เลขดัชนี (Index) ดังแสดงในรูป" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesNestOne.png)" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Element 0 of Tuple: 1\n", "Element 1 of Tuple: 2\n", "Element 2 of Tuple: ('pop', 'rock')\n", "Element 3 of Tuple: (3, 4)\n", "Element 4 of Tuple: ('dance', (1, 2))\n" ] } ], "source": [ "# แสดงสมาชิกแต่ละดัชนี\n", "\n", "print(\"Element 0 of Tuple: \", NestedT[0])\n", "print(\"Element 1 of Tuple: \", NestedT[1])\n", "print(\"Element 2 of Tuple: \", NestedT[2])\n", "print(\"Element 3 of Tuple: \", NestedT[3])\n", "print(\"Element 4 of Tuple: \", NestedT[4])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราเรียก ```NestedT``` ว่า \"Tuple หลัก\" และเรียก ```('pop', 'rock')```, ```(3, 4)``` และ ```('dance', (1, 2))``` ว่า \"Tuple สมาชิก\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถใช้เลขดัชนี (Index) ตัวที่สองต่อท้ายดัชนีตัวแรก เพิ่อเข้าถึงสมาชิกที่อยู่ใน Tuple สมาชิกได้ ดังรูป \n", "\n", "(ทั้งนี้ เลขดัชนี ไม่ว่าจะเป็นตัวแรกหรือตัวที่สอง ... จะต้องอยู่ในเครื่องหมายวงเล็บสี่เหลี่ยม `[]` เสมอ)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesNestTwo.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ลองเข้าถึงข้อมูล Tuple ซ้อน Tuple กัน\n", "\n", "ก่อนอื่น เข้าถึงสมาชิกแต่ละสมาชิกที่อยู่ใน Tuple สมาชิก (รูปข้างต้น)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Element 2, 0 of Tuple: pop\n", "Element 2, 1 of Tuple: rock\n", "Element 3, 0 of Tuple: 3\n", "Element 3, 1 of Tuple: 4\n", "Element 4, 0 of Tuple: dance\n", "Element 4, 1 of Tuple: (1, 2)\n" ] } ], "source": [ "# แสดงแต่ละสมาชิกที่อยู่ใน Tuple สมาชิก\n", "\n", "print(\"Element 2, 0 of Tuple: \", NestedT[2][0])\n", "print(\"Element 2, 1 of Tuple: \", NestedT[2][1])\n", "print(\"Element 3, 0 of Tuple: \", NestedT[3][0])\n", "print(\"Element 3, 1 of Tuple: \", NestedT[3][1])\n", "print(\"Element 4, 0 of Tuple: \", NestedT[4][0])\n", "print(\"Element 4, 1 of Tuple: \", NestedT[4][1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถใช้เลขดัชนี (Index) ตัวที่สามเข้าถึงข้อมูลสตริงที่เป็นสมาชิกของ Tuple สมาชิกได้เช่นกัน" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'r'" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# แสดงสมาชิกตัวแรกสุดที่อยู่ในสมาชิกลำดับที่ 2 ใน Tuple สมาชิก\n", "\n", "NestedT[2][1][0]" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'o'" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# แสดงสมาชิกตัวที่สองที่อยู่ในสมาชิกลำดับที่ 2 ใน Tuple สมาชิก\n", "\n", "NestedT[2][1][1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถใช้ภาพการแตกรากของต้นไม้แสดงตำแหน่งของสมาชิก โดยตัวเลขดัชนีที่แตกรากออกมาใหม่จะเป็นตำแหน่งของสมาชิกที่อยู่ในระดับที่ลึกลงไป \n", "\n", "คำสั่ง 2 บรรทัดข้างต้น สามารถแสดงเป็นภาพได้ดังนี้\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesNestThree.gif)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "นอกจากนี้ เรายังสามารถใช้เลขดัชนี (Index) ตัวที่สามเข้าถึงสมาชิกที่อยู่ลึกเข้าไปใน Tuple ซ้อน Tuple ซ้อน Tuple ได้เช่นกัน" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# แสดงสมาชิกตัวแรกที่อยู่ใน Tuple (1,2)\n", "\n", "NestedT[4][1][0]" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# แสดงสมาชิกตัวที่สองที่อยู่ใน Tuple (1,2)\n", "\n", "NestedT[4][1][1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "รูปต่อไปนี้แสดงความสำพันธ์ระหว่างรากที่แตกออกมากับสมาชิกที่ซ้อนอยู่ใน ```NestedT[4][1]```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/TuplesNestFour.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ ในภาษา Python มีชนิดของข้อมูลที่ใช้จัดเก็บและจัดเรียงข้อมูลต่างชนิดกันให้รวมกันเป็นชุดข้อมูลเดียวกัน และใช้ชื่อตัวแปรตัวเดียวกันได้ คือ Tuple กับ List (โดยตัวแปร Tuple ข้อมูลจะอยู่ภายใต้ \"( )\" แต่ ตัวแปร List ข้อมูลจะอยู่ภายใต้ \"[ ]\") แต่สิ่งที่แตกต่างกันคือ Tuple เป็นข้อมูลที่ไม่สามารถเปลี่ยนแปลงได้ (Immutable) หรือกล่าวอีกนัยหนึ่งก็คือ หลังจากที่ประกาศตัวแปรและกำหนดค่าให้กับ Tuple แล้ว มันจะไม่สามารถลบหรือเปลี่ยนแปลงค่าได้ ในขณะที่ List สามารถทำได้ (Mutable) \n", "\n", "ตัวอย่างต่อไปนี้เป็นการเปลี่ยนค่า ```NestedT[4][1][1]``` จาก 2 เป็น 100 จะเกิดเออเรอร์ (TypeError: 'tuple' object does not support item assignment)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'tuple' object does not support item assignment", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn [44], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mNestedT\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m4\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m100\u001b[39m\n", "\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment" ] } ], "source": [ "NestedT[4][1][1] = 100" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tuple vs. List ในภาษาไพธอน (สาเหตุที่ใช้ Tuple)\n", "\n", "$\\qquad$ ในภาษาไพธอน ชุดข้อมูลแบบ tuple เป็นชุดข้อมูลที่มีโครงสร้างใกล้เคียงกับ list สามารถเก็บข้อมูลภายในหลายจำนวนในตัวแปรเดียวกัน โดยจัดเก็บข้อมูลตามลำดับ\n", "มีการจัดเข้าถึงข้อมูลผ่านการเรียก Index ของชุดข้อมูลภายใน เหมือนกัน\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**แล้ว... เมื่อใดควรใช้ Tuples เมื่อใดควรใช้ Lists**\n", "\n", "หากเป็นข้อมูลที่ไม่ต้องการให้เปลี่ยนแปลง คุณควรเลือกประเภทของข้อมูลให้เป็น Tuple แทน List ซึ่งจะเป็นการป้องกันไม่ให้ข้อมูลเปลี่ยนโดยไม่ได้ตั้งใจ\n", "\n", "แต่ถ้าเป็นข้อมูลที่จะมีการขยายเพิ่มหรือย่อลดขนาดของข้อมูลระหว่างการรันโปรแกรม คุณต้องใช้ประเภทของข้อมูลเป็น List\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\qquad$ Tuple ไม่เพียงแค่ถูกใช้ในกรณีที่ต้องการเก็บชุดข้อมูลที่มีลำดับคล้ายกับ List และไม่ต้องการให้ค่าของข้อมูลเปลี่ยนแปลงในภายหลังเท่านั้น แต่ยังถูกใช้\n", "เพื่อเพิ่มประสิทธิภาพในการทำงานของคอมพิวเตอร์ เนื่องจากการใช้ Tuple **ช่วยประหยัดหน่วยความจำ** (ดูผลลัพธ์เปรียบเทียบได้จากโด้ดด้านล่างนี้) และยังช่วยลดเวลาในการประมวลผล (แม้จะใช้เวลาในการประมวลผลน้อยกว่าเล็กน้อยก็ตาม) ได้อีกด้วย นอกจากนี้ ยังสามารถทำการโคลนนิ่ง (Cloning) ข้อมูล ด้วยคำสั่ง ```tuple1 = tuple2``` ได้ โดยไม่ต้องเป็นกังกลว่าค่าเดิมเปลี่ยนจะถูกเปลี่ยน (เนื่องจากค่าของ Tuple เปลี่ยนแปลงไม่ได้! แต่...ในกรณีของ List คำสั่ง ```list1 = list2``` จะเป็นการก๊อปปี้ (Copy) ไม่ใช่การโคลนนิ่ง ซึ่งอาจจะทำให้ค่าเดิมของ List ถูกเปลี่ยนได้ในภายหลัง!)(รายละเอียดของการก๊อปปี้ (Copy) และการโคลนนิ่ง (Cloning) อยู่ใน [Lists](ch3-2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{note}\n", "Tuple ไม่ได้มีเฉพาะในภาษาไพธอน ภาษาคอมพิวเตอร์อื่นๆ ก็มีใช้ เช่น Lisp, Linda, C# ฯลฯ \n", "```\n" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "96 bytes for the list object.\n", "80 bytes for the tuple object.\n" ] } ], "source": [ "# โค้ดเปรียบเทียบประสิทธิภาพของหน่วยความจำระหว่าง Tuple กับ List\n", "# โดยใช้ฟังก์ชัน sys.getsizeof() ซึ่งจะคืนค่าเป็นขนาดของหน่วยความจำที่เก็บค่าอ็อบเจ็กต์ มีหน่วยเป็นไบต์ \n", "# Ref: https://towardsdatascience.com/python-tuples-when-to-use-them-over-lists-75e443f9dcd7\n", "\n", "import sys\n", "\n", "a_list = [1,2,3,4,5] # ตัวแปร List\n", "a_tuple = (1,2,3,4,5) # ตัวแปร Typle\n", "\n", "print(sys.getsizeof(a_list), 'bytes for the list object.') \n", "print(sys.getsizeof(a_tuple), 'bytes for the tuple object.') # \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เนื่องจาก Tuple เป็นโครงสร้างข้อมูลประเภท Immutable (เมื่อถูกสร้างขึ้นแล้ว จะเปลี่ยนค่าไม่ได้) จะถูกเก็บไว้ในหน่วยความจำบล็อกเดียว ในขณะที่ List เป็นข้อมูล Mutable (เมื่อถูกสร้างขึ้นแล้ว สามารถเพิ่มหรือลดจำนวนสมาชิก เปลี่ยนค่าข้อมูลได้) จะถูกเก็บไว้ในหน่วยความจำสองบล็อก (หนึ่งบล็อกเป็นบล็อกที่มีขนาดคงที่ และอีกบล็อกสำหรับจัดเก็บข้อมูล มีขนาดที่ไม่คงที่ ปรับขนาดได้ตามต้องการ)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## [Exercise]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```1.``` จาก Tuple ที่กำหนดค่าต่อไปนี้" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "genres_tuple = (\"pop\", \"rock\", \"soul\", \"dance pop\", \"soft rock\", \\\n", " \"edm\", \"brostep\", \"disco\") " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```1.1)``` จงหาขนาดของ Tuple ```genres_tuple```\n" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```1.2)``` จงเขียนโค้ดเข้าถึงสมาชิกที่มีเลขดัชนีเป็น 3 (สมาชิกที่มีเลขดัชนี 3 มีค่า?)\n" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```1.3)``` จงทำการตัด (Slicing) เพื่อให้ได้สมาชิกที่เลขดัชนีเป็น 3, 4 และ 5\n" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```1.4)``` จงหาสมาชิกสามตัวแรกที่อยู่ใน Tuple ```genres_tuple```\n" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```1.5)``` จงหาสมาชิกตัวสุดท้ายที่อยู่ใน Tuple ```genres_tuple```\n" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```1.6)``` จงหาเลขดัชนีของ ```\"edm\"``` (edm: electronic dance music)\n" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```2.``` จงเขียนโค้ดกลับลำดับสมาชิกของ Tuple ```tuple_a = (\"ฉัน\", \"ชอบ\", \"เธอ\")``` (เรียงลำดับย้อนกลับ)\n" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```3.``` จงเขียนโค้ดจัดเรียงลำดับตัวเลขใน Tuple ```tuple_c = (-5, 1, -3, 9, 3, 6,-1, -3, 6, 2, 8)``` จากน้อยไปมาก\n" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---------" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Author\n", "\n", "S.C.\n", "\n", "### Change Log\n", "\n", " \n", "| Date | Version | Change Description |\n", "|---|---|---|\n", "| 08-08-2021 | 0.1 | First edition |\n", "| 05-05-2022 | 0.2 | Fix the typo, minor change |\n", "| | | |\n", "| | | |\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel(3.8.13))", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.13" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false }, "vscode": { "interpreter": { "hash": "e921dbf9f2d20a8528fa054ff97aae3eb23f1abc9a6f29b7bcee4307a5b88bad" } } }, "nbformat": 4, "nbformat_minor": 4 }