{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/python_with_Birds.gif)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "(ch4)=\n", "# Sets (เซ็ท)\n", "\n", "**Set (เซ็ต)** เป็นอออบเจกต์ที่ใช้เก็บข้อมูลที่ไม่ซ้ำกันรวมเป็นชุดข้อมูลชุดเดียวกัน เราสามารถใช้ Set หาค่าที่ไม่ซ้ำกันภายในลิสต์ ใช้ตรวจสอบข้อมูลที่มีอยู่แล้ว หรือดำเนินการทางคณิตศาสตร์ที่เกี่ยวกับเซ็ท เช่น Intersection, Union, Difference และ Symmetric difference ได้\n", "\n", "\n", "คุณอาจจะเคยเรียนเรื่องเซ็ท (Set) และทฤษฎีเซตในวิชาคณิตศาสต์กันมา และน่าจะคุนเคยกับแผนภาพของเวน (Venn Diagram) ประมาณนี้...\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/venn_diagram.png)\n", "\n", "(src: https://texample.net//tikz/examples/set-operations-illustrated-with-venn-diagrams/)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "แต่ถ้าจำไม่ได้หรือไม่คุ้นเลย ก็ไม่ต้องตกใจ ในบทนี้จะเรียนรู้ข้อมูลชนิด Sets (เซ็ท) ในภาษาไพธอนแบบเข้าใจง่ายๆ กัน\n", "\n", "เราจะทำความรู้จักกับ Sets ว่าคืออะไร เรียนรู้วิธีการประกาศและการใช้งาน Sets เรียนรู้เมธอดที่ใช้ในการเพิ่มและลบข้อมูลของ Set รวมถึงวิธีดำเนินการทางคณิตศาสตร์ที่เกี่ยวข้องกับเซ็ตเบื้องต้น (Union, Intersection, Difference และ Symmetric difference)\n", "\n", "Ref:\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set (เซ็ต) คือ?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Set (เซ็ต)** เป็นออบเจ็คที่สร้างขึ้นจากคลาส `set` ใช้สำหรับเก็บข้อมูลที่ไม่ซ้ำกันรวมเป็นชุดข้อมูลชุดเดียวกัน ซึ่งข้อมูลภายเซ็ตจะไม่มีลำดับของข้อมูล\n", "\n", "**คุณสมบัติของ Set**\n", "* องค์ประกอบหรือสมาชิกภายในเซ็ทจะไม่ซ้ำกัน (ซ้ำกันไม่ได้ ไม่อนุญาต)\n", "* ข้อมูลภายในเซ็ทจะไม่เรียงลำดับ (ทำให้การประมวลผลทำได้อย่างรวดเร็ว)\n", "* เป็นชนิดข้อมูลแบบเปลี่ยนแปลงได้ (Mutable Types) แต่สมาชิกที่อยู่ภายใน Set ต้องเป็นประเภทที่เปลี่ยนแปลงไม่ได้ (Immutable Types)\n", "\n", "เราจะมาดูกันว่าคุณสมบัติข้างต้นนั้นหมายความว่าอย่างไร และเราจะใช้งาน Set ใน Python ได้อย่างไร" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## การประกาศและใช้งาน Set\n", "\n", "**การสร้างเซ็ตของข้อมูล**\n", "เราสามารถสร้าง Sets ได้ 2 วิธี คือ \n", "* การสร้างโดยใช้วงเล็บปีกกา (curly braces) `{...}` และ \n", "* การสร้างโดยใช้ฟังก์ชัน `set( )`\n", "\n", "\n", "**1) การสร้างโดยใช้เครื่องหมาย `{...}`**\n", "\n", "โดยนำข้อมูลทั้งหมดใส่ภายในเครื่องหมายวงเล็บปีกกา {...} แล้วทำการคั่นแต่ละสมาชิกด้วยเครื่องหมายคอมมา (,) ซึ่งวิธีนี้เป็นวิธีที่ง่ายและใช้บ่อยที่สุด" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "[1, 1, 1, 1, 2, 3, 4, 5, 'rock', 'rock', 'pop']" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# สร้าง list ด้วยวงเล็บสี่เหลียม []\n", "[1,1,1,1,2,3,4,5,'rock', 'rock', 'pop']" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{1, 2, 3, 4, 5, 'pop', 'rock'}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# สร้าง set ด้วยวงเล็บปีกกา {}\n", "{1,1,1,1,2,3,4,5,'rock', 'rock', 'pop'}" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'R&B', 'disco', 'hard rock', 'pop', 'rock', 'soul'}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# สร้างตัวแปรเก็บข้อมูล set\n", "\n", "set1 = {\"pop\", \"rock\", \"soul\", \"hard rock\", \"rock\", \"R&B\", \"rock\", \"disco\"}\n", "set1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "จากตัวอย่างข้างต้นเป็นการยืนยันว่า Set จะประกอบด้วยสมาชิกที่มีค่า**ไม่ซ้ำค่ากัน!** ถ้าหากว่าข้อมูลที่ประกาศซ้ำกัน Python จะลบรายการที่ซ้ำกัน (ให้เหลือเพียงรายการเดียว) โดยอัตโนมัติ" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/SetsUnique.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "องค์ประกอบหรือสมาชิกที่บรรจุอยู่ภายใน Set จะ**ไม่จำกัดจำนวน**และ**เก็บข้อมูลได้หลายชนิดภายในเซ็ตเดียวกันได้** ไม่ว่าจะเป็น เลขจำนวนเต็ม(integer), เลขทศนิยม(float), tuple, ข้อความ(string) ก็ตาม **แต่...ไม่สามารถเก็บข้อมูลที่แก้ไขข้อมูล(mutable)** เช่น ลิสต์ (list), เซ็ต(set) หรือ ดิกชันนารี(dictionary) ได้\n", "\n", "ยกตัวอย่างเช่น เราสามารถสร้างตัวแปรที่ภายในเป็น tuple ซึ่งเป็นข้อมูลแบบ immutable ได้" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{('pop', 'pop rock', 'teen pop'), ('rock', 'hard rock', 'electronic rock')}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "set2 = {(\"pop\", \"pop rock\", \"teen pop\"), (\"rock\", \"hard rock\", \"electronic rock\")} # ภายในเป็น immutable\n", "set2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "แต่ถ้าภายในเป็น list หรือ set ซึ่งเป็นข้อมูลแบบ mutable จะเกิดข้อผิดพลาด (TypeError: unhashable type: 'list' ('set')) เนื่องจาก สมาชิกที่อยู่ภายในเซ็ตต้องเป็น **Hashtable object** (ออบเจ็กต์ที่มีค่าแฮช (hash; ตรวจสอบโดยใช้ฟังก์ชัน hash()) และมีค่าเดิมไม่เปลี่ยนแปลงตลอดช่วงอายุของมัน (ค่า id ของออบเจ็กต์เป็นค่าเดิมเสมอ))" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "tags": [] }, "outputs": [ { "ename": "TypeError", "evalue": "unhashable type: 'list'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn [5], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m set3 \u001b[38;5;241m=\u001b[39m {[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpop\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpop rock\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mteen pop\u001b[39m\u001b[38;5;124m\"\u001b[39m], [\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrock\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhard rock\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124melectronic rock\u001b[39m\u001b[38;5;124m\"\u001b[39m]}\n", "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'list'" ] } ], "source": [ "set3 = {[\"pop\", \"pop rock\", \"teen pop\"], [\"rock\", \"hard rock\", \"electronic rock\"]} # ภายในเป็น mutable" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "set4 = {{\"pop\", \"pop rock\", \"teen pop\"}, {\"rock\", \"hard rock\", \"electronic rock\"}} # ภายในเป็น mutable" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "กล่าวคือ สมาชิกที่อยู่ภายใน Set ต้องเป็นประเภทที่เปลี่ยนแปลงไม่ได้ (Immutable Types) เท่านั้น" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**2) การสร้างโดยใช้ฟังก์ชัน `set( )`**\n", "\n", "เราสามารถสร้างเซ็ตของข้อมูลโดยใช้ฟังก์ชัน `set( )`\n", "\n", "> ```x = set()```\n", "\n", "ณ ที่นี้ `` คือ ออบเจ็กต์ใดๆ ที่เราสามารถทำการวนซ้ำกับมันได้ ซึ่งรวมไปถึง lists, tuples, dictionaries, sets หรือแม้แต่ strings ก็ถือเป็น Iterable เช่นกัน " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ตัวอย่างต่อไปนี้เป็นการสร้างเซ็ทจากลิสต์ที่มีข้อมูลหลายชนิดภายในลิสต์เดียวกัน" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{65, '00:42:19', None, 10.0, 46.0, 'Thriller', 'Pop, Rock, R&B', '30-Nov-82', 'Michael Jackson', 1982}\n" ] } ], "source": [ "# เปลี่ยนข้อมูล List ให้เป็น Set\n", "\n", "album_list = [\"Michael Jackson\", \"Thriller\", 1982, \"00:42:19\", \\\n", " \"Pop, Rock, R&B\", 46.0, 65, \"30-Nov-82\", None, 10.0]\n", "album_set = set(album_list) \n", "print(album_set)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ลองสร้างชุดข้อมูล Set ของรูปแบบเพลงตามจังหวะ (genres) กัน" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'soul', 'soft rock', 'rock', 'folk rock', 'disco', 'pop', 'hard rock', 'R&B', 'progressive rock'}\n", "{'soul', 'soft rock', 'rock', 'folk rock', 'disco', 'pop', 'hard rock', 'R&B', 'progressive rock'}\n" ] } ], "source": [ "# เปลี่ยนข้อมูล List ให้เป็น Set\n", "\n", "music_genres = set([\"pop\", \"pop\", \"rock\", \"folk rock\", \"hard rock\", \"soul\", \\\n", " \"progressive rock\", \"soft rock\", \"R&B\", \"disco\", \"disco\"])\n", "print(music_genres)\n", "\n", "# เปลี่ยนข้อมูล Set ให้เป็น Set\n", "print(set(music_genres))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{note}\n", "ตัวอย่างข้างต้นแสดงให้เห็นว่า เราสามารถใช้ฟังก์ชัน set( ) หาค่าที่ไม่ซ้ำกันภายในลิสต์ได้ ! และข้อมูลภายในเซ็ตจะไม่มีลำดับของข้อมูล!\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "สตริงเป็นข้อมูล iterable สามารถวนซ้ำได้ ดังนั้นจึงสามารถส่งผ่านสตริงไปยังฟังก์ชัน set() ได้เช่นกัน \n", "\n", "ตัวอย่างต่อไปนี้แสดงให้เห็นว่า ฟังก์ชัน `list()` สร้างลิสต์ของอักขระทุกตัวที่อยู่ในสตริง (มีลำดับ) และในทำนองเดียวกัน ฟังก์ชัน set(s) สร้างเซ็ทของอักขระที่อยู่ในสตริง (ไม่มีลำดับ)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Size of ['P', 'r', 'a', 'c', 't', 'i', 'c', 'e', ' ', 'm', 'a', 'k', 'e', 's', ' ', 'p', 'e', 'r', 'f', 'e', 'c', 't']: 22\n" ] } ], "source": [ "str_list = list(\"Practice makes perfect\")\n", "print(f\"Size of {str_list}: {len(str_list)}\")\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Size of {'p', 't', 'P', 'r', 'i', 's', 'k', 'f', 'e', 'c', ' ', 'm', 'a'}: 13\n" ] } ], "source": [ "str_set = set(\"Practice makes perfect\")\n", "print(f\"Size of {str_set}: {len(str_set)}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{note}\n", "เมื่อฟังก์ชัน `set()` รับอาร์กิวเมนต์ที่เป็น iterable ฟังก์ชัน `set()` จะสร้าง**เซ็ทขององค์ประกอบที่ประกอบเป็น iterable นั้นๆ** ในขณะที่การวางออบเจ็กต์ในวงเล็บปีกการ `{...}` จะสร้าง**เซ็ทของออบเจ็กต์ตัวเดิมนั้นๆ** แม้ว่าออบเจ็กต์ตัวเดิมนั้นจะเป็น iterable ก็ตาม\n", "```\n", "\n", "\\>>> set(\"Engineering\") # สร้างเซ็ทขององค์ประกอบที่ประกอบเป็น iterable (str)\n", "\n", "{'E', 'r', 'i', 'g', 'n', 'e'}\n", "\n", "\\>\\>\\> {\"Engineering\"} # สร้างเซ็ทของออบเจ็กต์ตัวเดิมนั้นๆ (str)\n", "\n", "{'Engineering'}\n", "\n", "\\>\\>\\> set([\"Engineering\"]) # สร้างเซ็ทขององค์ประกอบที่ประกอบเป็น iterable (list)\n", "\n", "{'Engineering'}\n", "```\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## การดำเนินการพื้นฐานกับ Sets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เนื่องจาก Sets เป็นข้อมูลแบบ Immutable เราสามารถเปลี่ยนแปลง/แก้ไข เช่น การเพิ่มหรือลบข้อมูล ภายใน Sets ได้\n", "\n", "เราจะลองเขียนโค้ดเปลี่ยนขอมูลภายใน Set `A` กัน\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black', 'Thriller'}" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ประกาศตัวแปร A\n", "\n", "A = set([\"Thriller\", \"Back in Black\", \"AC/DC\"])\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**เพิ่มข้อมูลเข้าไปในเซ็ตโดยใชัเมธอด `add( )`**" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black', 'NSYNC', 'Thriller'}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# เพิ่มสมาชิกใหม่เข้าไปในเซ็ต\n", "\n", "A.add(\"NSYNC\")\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ถ้าเราเพิ่มข้อมูลที่มีอยู่แล้วในเซ็ต A เช่น เพิ่ม *\"NSYNC\"* เข้าไปอีกครั้ง ก็ไม่เกิดการเปลี่ยนแปลง เพราะข้อมูลในเซ็ตจะต้องไม่ซ้ำกัน!" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black', 'NSYNC', 'Thriller'}" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ลองเพิ่มสมาชิกใหม่ที่ซ้ำกับข้อมูลเดิมที่มีอยู่แล้ว\n", "\n", "A.add(\"NSYNC\")\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**เพิ่มข้อมูลครั้งละหลายตัวเข้าไปในเซ็ตโดยใชัเมธอด update( )**\n", "\n", "ในการเพิ่มข้อมูลเข้าไปในเซ็ตนั้น นอกจากการเพิ่มข้อมูลเข้าไปทีละตัวด้วยเมธอด **add( )** แล้ว\n", "เรายังสามารถเพิ่มข้อมูลครั้งละหลายตัวได้โดยใช้เมธอด **update( )** \n", "\n", "โดยอาร์กิวเมนต์ที่ส่งให้กับเมธอดนี้ต้องเป็นออบเจกต์ iterable เช่น tuples, ลิสต์ (lists), ข้อความ (string) หรือ เซ็ต(set)\n" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black', 'Bye Bye Bye', 'NSYNC', 'Thriller'}" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.update({\"NSYNC\", \"Bye Bye Bye\"})\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "และแน่นอน ข้อมูลใหม่จะไม่ซ้ำกับข้อมูลที่มีอยู่เดิม" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'banana', 'microsoft', 'apple', 'google', 'cherry'}\n" ] } ], "source": [ "x = {\"apple\", \"banana\", \"cherry\"}\n", "y = {\"google\", \"microsoft\", \"apple\"}\n", "\n", "x.update(y)\n", "\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**การลบข้อมูลออกจากเซ็ตโดยใช้เมธอด `remove( )`**\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black', 'Bye Bye Bye', 'Thriller'}" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ลบข้อมูลออกจากเซ็ต\n", "\n", "A.remove(\"NSYNC\")\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ลองรั้นโค้ดข้างต้นอีกที แล้วดูว่าจะเกิดอะไรขึ้น??" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{error}\n", "\n", "* หากข้อมูลที่จะลบไม่มีอยู่ในเซ็ต จะเกิดข้อผิดพลาดขึ้น เราจึงควรจะทราบข้อมูลที่ต้องการจะลบก่อนเรียกใช้เมธอด `remove( )`\n", " \n", "* การลบข้อมูลออกจากเซ็ตมีอีกวิธี คือ การใช้เมธอด `discard( )` \n", "โดยเมธอดนี้จะไม่เกิดการเปลี่ยนแปลงใดๆ (ไม่เกิดข้อผิดพลาดขึ้น) หากข้อมูลที่ต้องการจะลบไม่มีอยู่ในเซ็ต\n", " \n", "*เมธอด `clear( )` ใช้ลบข้อมูลทั้งหมดออกจากเซ็ต\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**การตรวจสอบค่าใน Set ด้วยตัวดำเนินการ `in`** \n", "\n", "เราสามารถใช้ตัวดำเนินการ **`in`** ตรวจสอบว่ามีค่าที่เราต้องการอยู่ในเซ็ตหรือไม่ โดยตัวดำเนินการ `in` ส่งค่ากลับเป็น `True` ถ้าหากค่าดังกล่าวมีอยู่ภายใน Set ไม่เช่นนั้นมันส่งค่ากลับเป็น `False`" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ตรวจสอบว่าอยู่ใน Set หรือไม่\n", "\n", "\"AC/DC\" in A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ตัวดำเนินการ `not in` จะตรงกันข้ามกับตัวดำเนินการ `in` " ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ตรวจสอบว่าอยู่ใน Set หรือไม่\n", "\n", "\"AC/DC\" not in A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ลบข้อมูลทั้งหมดออกจากเซ็ตโดยใช้เมธอด `clear()` กลายเป็นเซ็ตว่าง (null Set / empty set) เมื่อเช็คจำนวนสมาชิก จะส่งค่ากลับเป็นศูนย์" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "set()\n", "0\n" ] } ], "source": [ "# ลบข้อมูลทั้งหมดออกจากเซ็ต\n", "A.clear()\n", "print(A) \n", "print(len(A))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## การดำเนินการทางคณิตศาสตร์ที่เกี่ยวกับ Sets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถดำเนินการทางคณิตศาสตร์กับข้อมูลแบบเซ็ตได้ เช่น การรวมข้อมูลกัน (Union (ยูเนียน)), การเลือกข้อมูลเฉพาะที่ซ้ำซ้อนกัน (Intersection (อินเตอร์เซคชัน)) และ การเลือกข้อมูลเฉพาะข้อมูลที่แตกต่างจากอีกเซ็ตข้อมูล (Difference) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราจะพิจารณาเซ็ตสองชุดต่อไปนี้" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "tags": [] }, "outputs": [], "source": [ "# ตัวอย่างของ Sets\n", "\n", "album_set1 = set([\"Thriller\", 'AC/DC', 'Back in Black'])\n", "album_set2 = set([ \"AC/DC\", \"Back in Black\", \"The Dark Side of the Moon\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/SetsSamples.png)\n" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "scrolled": true, "tags": [] }, "outputs": [ { "data": { "text/plain": [ "({'AC/DC', 'Back in Black', 'Thriller'},\n", " {'AC/DC', 'Back in Black', 'The Dark Side of the Moon'})" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# แสดงข้อมูลทั้งสอง Set\n", "\n", "album_set1, album_set2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**การเลือกข้อมูลเฉพาะที่ซ้ำซ้อนกัน (Intersection)**\n", "\n", "การเลือกข้อมูลเฉพาะที่ซ้ำซ้อนกัน (Intersection) เป็นการค้นหาข้อมูลเฉพาะข้อมูลที่มีร่วมกันหรือมีเหมือนกันระหว่างข้อมูลในแต่ละเซ็ต โดยอาจจะใช้เครื่องหมายดำเนินการ **`&`** หรือจะใช้เมธอด `intersection( )` ในการดึงข้อมูลที่มีร่วมกันก็ได้\n", "\n", "\n", "\n", "เนื่องจากข้อมูลทั้งสองชุดมี AC/DC และ Back in Black ร่วมกัน เราจึงสามารถแสดงข้อมูลที่มีร่วมกันด้วยจุดตัดของวงกลมสองวงได้ ดังรูป" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/SetsLogic.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ใช้เครื่องหมายดำเนินการ **“&”** ในการดึงข้อมูลที่มีร่วมกัน" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black'}" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# เลือกเฉพาะข้อมูลที่ซ้ำซ้อนกัน (Intersection)\n", "\n", "intersection = album_set1 & album_set2\n", "intersection" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "หรือจะใช้เมธอด `intersection( )` ในการดึงข้อมูลที่มีร่วมกันระหว่าง `album_list1` กับ `album_list2` ก็ได้" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black'}" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "album_set1.intersection(album_set2) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "เราสามารถแสดงข้อมูลที่มีร่วมกันด้วยจุดตัดของวงกลมสองวงได้ ดังรูป" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/SetsIntersect.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**การเลือกข้อมูลเฉพาะข้อมูลที่ต่างจากอีกเซ็ตข้อมูล (Difference)**\n", "\n", "การเลือกข้อมูลเฉพาะข้อมูลที่ต่างจากอีกเซ็ตข้อมูล (Difference) คือ การหาเฉพาะข้อมูลที่มีอยู่ในเซ็ตหนึ่ง แต่ข้อมูลดังกล่าวไม่มีอยู่ในอีกเซ็ตหนึ่งที่นำมาเปรียบเทียบ โดยอาจจะใช้เครื่องหมายลบ **`-`** หรือจะใช้เมธอด `difference( )` ก็ได้\n", "\n", "\n", "เราสามารถหา**สมาชิกทุกตัวที่มีอยู่เฉพาะใน `album_set1` ได้โดยใช้เครื่องหมายลบ `-`** " ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'Thriller'}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# หาข้อมูลที่ต่างที่อยู่ใน set1 แต่ไม่อยู่ใน set2\n", "\n", "difference1_2 = album_set1 - album_set2 \n", "difference1_2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "หรือจะใช้เมธอด เมธอด `difference( )` ก็ได้" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'Thriller'}" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# หาข้อมูลที่ต่างที่อยู่ใน set1 แต่ไม่อยู่ใน set2\n", "\n", "album_set1.difference(album_set2) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ผลลัพธ์ที่ได้คือ สมาชิกทุกตัวที่มีอยู่เฉพาะใน `album_set1` เท่านั้น แสดงได้ดังรูปต่อไปนี้\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/SetsLeft.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "หากต้องการหาสมาชิกทุกตัวที่มีอยู่เฉพาะใน `album_set2` ก็ทำได้โดยวิธีเดียวกัน\n" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'The Dark Side of the Moon'}" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# หาข้อมูลที่ต่างที่อยู่ใน set2 แต่ไม่อยู่ใน set1\n", "\n", "difference2_1 = album_set2 - album_set1 \n", "difference2_1" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'The Dark Side of the Moon'}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# หาข้อมูลที่ต่างที่อยู่ใน set2 แต่ไม่อยู่ใน set1\n", "\n", "album_set2.difference(album_set1) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/SetsRight.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**การรวมข้อมูลกัน (Union)**\n", "\n", "การรวมข้อมูลกัน (Union) เป็นการดึงข้อมูลทั้งหมดจากแต่ละเซ็ตแล้วรวมเข้าด้วยกัน ถ้าข้อมูลซ้ำกันจะดึงข้อมูลดังกล่าวออกมาเพียงข้อมูลเดียว ดังรูป \n", "\n", "การรวมข้อมูลสามารถทำได้โดยใช้เครื่องหมายดำเนินการ **` | `** หรือจะใช้เมธอด `union( )` ก็ได้\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/SetsUnion.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "การรวมข้อมูลโดยใช้เครื่องหมายดำเนินการ **` | `**" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black', 'The Dark Side of the Moon', 'Thriller'}" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# รวมข้อมูลของทั้งสองเซ็ต\n", "\n", "union = album_set1 | album_set2\n", "union" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "หรือจะรวมข้อมูลโดยใช้เมธอด `union( )` ก็ได้" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black', 'The Dark Side of the Moon', 'Thriller'}" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# รวมข้อมูลของทั้งสองเซ็ต\n", "\n", "album_set1.union(album_set2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**การเลือกข้อมูลจากทุกเซ็ตโดยเลือกเฉพาะข้อมูลที่แตกต่างจากเซ็ตอื่นๆ (Symmetric difference)**\n", "\n", "\n", "คือ การเลือกข้อมูลจากทุกเซตโดยเลือกเฉพาะข้อมูลที่เซตนั้นๆ มีแตกต่างจากเซตอื่น(symmetric difference) \n", "คือการดึงข้อมูลที่มีอยู่เฉพาะในแต่ละเซ็ตแต่ไม่มีอยู่ในเซ็ตอื่นๆ ที่นำมาใช้เปรียบเทียบ พูดอีกอย่างหนึ่งก็คือ... การนำสมาชิกของทุกเซ็ตมารวมกัน (Union) แต่ไม่นับเอาสมาชิกมีเหมือนกันหรือมีร่วมกัน (Intersection) นั่นเอง โดยจะใช้เครื่องหมายดำเนินการ `^` (XOR) หรือจะใช้เมธอด `symmetric_difference( )` ในการดึงข้อมูลก็ได้" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](images/SymmetricDifference.png)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'The Dark Side of the Moon', 'Thriller'}" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# เลือกข้อมูลจากทุกเซ็ตโดยเลือกเฉพาะข้อมูลที่แตกต่างจากเซ็ตอื่นๆ (Symmetric difference)\n", "\n", "symmetric_difference = album_set1 ^ album_set2\n", "symmetric_difference" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "หรือจะรวมข้อมูลโดยใช้เมธอด `symmetric_difference( )` ก็ได้" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'The Dark Side of the Moon', 'Thriller'}" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# รวมข้อมูลของทั้งสองเซ็ต\n", "\n", "album_set1.symmetric_difference(album_set2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ซึ่งจะมีค่าเท่ากับ การนำสมาชิกของทุกเซ็ตมารวมกัน (Union) แต่ไม่นับเอาสมาชิกมีเหมือนกันหรือมีร่วมกัน (Intersection)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'The Dark Side of the Moon', 'Thriller'}" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "union - intersection" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## การเปรียบเทียบ Sets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "นอกจากนี้ เรายังสามารถทำการเปรียบเทียบ Set เพื่อตรวจสอบความสัมพันธ์ระหว่างเซ็ตสองเซ็ตได้ เช่น ตรวจสอบว่าเซ็ตที่เราต้องการเป็น superset (หรือ power set (เพาเวอร์เซ็ต)) หรือเป็น subset (สับเซ็ต (เซ็ตย่อย)) ของอีกเซ็ตหรือไม่ โดยใช้เมธอด `issuperset( )` และ `issubset( )` ตามลำดับ " ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ตรวจสอบว่าเป็น superset หรือไม่\n", "\n", "set(album_set1).issuperset(album_set2) # or\n", "# album_set1.issuperset(album_set2) " ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ตรวจสอบว่าเป็น subset หรือไม่\n", "\n", "set(album_set2).issubset(album_set1) # or\n", "# album_set2.issubset(album_set1) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ตัวอย่างถัดไปเป็นตัวอย่างที่ `issubset()` และ `issuperset()` คืนค่าจริง (**True**) ทั้ง 2 ตัวอย่าง\n" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'AC/DC', 'Back in Black', 'Thriller'}" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "album_set1" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ตรวจสอบว่าเป็น subset หรือไม่\n", "\n", "set({\"Back in Black\", \"AC/DC\"}).issubset(album_set1) " ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ตรวจสอบว่าเป็น superset หรือไม่\n", "\n", "album_set1.issuperset({\"Back in Black\", \"AC/DC\"}) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## [Exercise]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`1.` จงแปลงลิสต์ `['rap','house','electronic music', 'rap']` ให้เป็นข้อมูลชนิดเซ็ต" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "tags": [] }, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[//]: #\"\n", "
Click here for the solution\n", "\n", "```python\n", "set(['rap','house','electronic music', 'rap']) # {'electronic music', 'house', 'rap'}\n", "\n", "```\n", "\n", "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`2.` กำหนด ลิสต์ `A = [1, 2, 2, 1]` และเซ็ต `B = set([1, 2, 2, 1])`, ถามว่า `sum(A) == sum(B)` หรือไม่?\n" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "tags": [] }, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[//]: #\"\n", "
Click here for the solution\n", "\n", "```python\n", "A = [1, 2, 2, 1] \n", "B = set([1, 2, 2, 1])\n", "print(\"the sum of A is:\", sum(A)) # the sum of A is: 6\n", "print(\"the sum of B is:\", sum(B)) # the sum of B is: 3\n", "print(sum(A)==sum(B)) # False\n", "```\n", "\n", "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`3.` จากเซ็ต `frontend_developer_lang` และเซ็ต `backend_developer_lang` ต่อไปนี้ \n", "จงสร้างเซ็ตชุดใหม่ `all_developer_lang` ที่เกิดจากการรวมข้อมูลกัน (Union) ระหว่างสองเซ็ตนี้**โดยที่ไม่ใช้เมธอด `union()`**\n" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "tags": [] }, "outputs": [], "source": [ "# เขียนโค้ดต่อด้านล่าง แล้วกด Shift+Enter\n", "\n", "album_set1 = set([\"Thriller\", 'AC/DC', 'Back in Black'])\n", "album_set2 = set([ \"AC/DC\", \"Back in Black\", \"The Dark Side of the Moon\"])\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[//]: #\"\n", "
Click here for the solution\n", "\n", "```python\n", "frontend_developer_lang = set(['HTML', 'CSS', 'JavaScript', 'Angular', 'ReactJS', 'Node.js', '.Net', 'Python'])\n", "backend_developer_lang = set(['PHP', 'C++', 'Java', 'Python', 'Ruby', 'Node.js', '.Net', 'JavaScript'])\n", "\n", "all_developer_lang = set() # สร้างเซ็ตว่าง\n", "all_developer_lang.update(frontend_developer_lang, backend_developer_lang) # เพิ่มเซ็ททั้งสองเข้าเป้นสมาชิก\n", "all_developer_lang```\n", "\n", "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`4.` จากข้อก่อนหน้า จงตรวจสอบว่า `frontend_developer_lang` เป็น subset ของ `all_developer_lang` หรือไม่\n" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "tags": [] }, "outputs": [], "source": [ "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[//]: #\"\n", "
Click here for the solution\n", "\n", "```python\n", "# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter\n", "frontend_developer_lang.issubset(all_developer_lang) # True\n", "```\n", "\n", "
\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": true } }, "nbformat": 4, "nbformat_minor": 4 }