رفتن به مطلب
جامعه‌ی برنامه‌نویسان مُدرن ایران

پرچمداران

  1. کامبیز اسدزاده

    کامبیز اسدزاده

    بنیـــان گذار


    • امتیاز

      1

    • تعداد ارسال ها

      368


  2. سید محمد عباسی

    سید محمد عباسی

    کاربـــر رسمی


    • امتیاز

      1

    • تعداد ارسال ها

      41



مطالب محبوب

در حال نمایش مطالب دارای بیشترین امتیاز از زمان یکشنبه, 27 بهمن 1398 در همه بخش ها

  1. 1 امتیاز
    آموزش زبان برنامه‌نویسی سوئیفت - جلسه هشتم مواردی که در این جلسه یاد خواهید گرفت: دیکشنری ( Dictionary ) دیشکنری‌ها چیستند؟ به طور ساده و خلاصه؛ یکی از نوع‌های مجموعه‌ است که مقادیر یا همان داده‌ها را به صورت کلید/مقدار ( key/value ) ذخیره می‌کند و همچنین نامرتب است و داده‌های تکراری را فقط یک‌بار مورد ذخیره! این‌کار به شدت می‌تواند به برنامه‌نویس کمک کند تا راحت‌تر، بهتر و سریع‌تر به داده‌های خود از طریق کلید ( key ) دسترسی داشته باشد و همچنین کُدی خوانا‌تر داشته باشد. برای این‌که این موضوع برای شما عزیزان شفاف‌تر شود و بهتر بتوانید این موضوع را درک کنید، شروع به ایجاد دیکشنری خودمان خواهیم کرد و در ادامه، توضیحات لازم را ارائه خواهیم داد. برای ایجاد یک دیکشنری، به چهار صورت می‌توانیم عمل کنیم؛ استفاده از کلاس Dictionary و سپاس در بین دو علامت <> کلید و مقدار خود را قرار می‌دهیم <Dictionary<Key, Value که البته باید در نظر داشته باشید، Key و Value نوع دادهایی هستند که باید قرار گیرند و بعد‌ا مقدار‌دهی بر اساس نوع‌های داده خواهد بود نه مستقیما مقدادهی کنید! مانند؛ <Dictionary<String, Double تعریف یک متغییر و سپس استفاده از الگوی؛‌ ()[String : String ] استفاده از روش دوم با این تفاوت که شما می‌بایست، دیکشنری خود را همانند تعریف یک متغییر به صورت صریح بنویسید! شما می‌توانید فقط از [] به صورت مستقیم استفاده کنید و داده‌ها را اضافه کنید، مانند؛ ["var products = ["www.fanoox.com : "MacBook Pro از اولین مورد شروع خواهیم کرد، پس به این شکل عمل می‌کنیم؛ var users_and_passwords= Dictionary<String, String>() users_and_passwords["Mohammad"] = "!#$#@%#$!#@$" users_and_passwords["Ali"] = ")+_)(*&^^%" users_and_passwords = ["Ali" : "_)(*&^%^&*", "Hamed" : "123456789%$#@!#$^%!$1009876!!$$%!$54321"] print(users_and_passwords) /* ["Ali" : "_)(*&^%^&*", "Hamed" : "123456789%$#@!#$^%!$1009876!!$$%!$54321" ] */ همان‌طور که مشاهده می‌کنید، یک متغییر تعریف کرده و سپس از کلاس Dictionary استفاده کردیم که در بین دو علامت <> ( بزرگ‌تری و کوچک‌تری ) نوع‌هایی که می‌خواهیم از آن‌ها در برنامه‌مان استفاده کنیم، به کار بردیم. شما می‌توانید هم به تنهایی و هم گروهی، مقداردهی را شروع کنید! در قطعه‌کد بالا می‌بینید که خط ۲ و ۳، به صورت تَکی و خط ۴ به صورت گروهی مقداردهی شده است و در نهایت در خط ۵ آن را چاپ می‌کنیم. توجه داشته باشید که اگر در حالت گروهی بخواهید مقدادهی کنید،‌ مقادیر قبلی از بین خواهند رفت! در حالی که اگر شما به صورت تکی مقداردهی کنید، این اتفاق نخواهد افتاد. نکته اگر به صورت تَکی بخواهید مقداردهی کنید، هیچ اتفاقی برای مقادیر دیگر نخواهد افتاد! اما اگر گروهی مقداردهی کنید، داده‌های قبلی به کل پاک و داده‌های جدید، قرار خواهند گرفت. دومین نوع تعریف بدون استفاده از کلاس است؛ var languages_and_framework = [String : String]() languages_and_framework["C++"] = "Qt Creator " languages_and_framework["PHP"] = "Laravel" print(languages_and_framework) /* ["C++" : "Qt Creator ", "PHP" : "Laravel"] */ در سومین حالت تعریف به این شکل عمل خواهیم کرد؛‌ var languages_and_framework : [String : String] = ["C++" : "Qt Creator", "Javascript" : "Angular.js"] print(languages_and_framework) /* ["C++" : "Qt Creator", "Javascript" : "Angular.js"] */ و در نهایت در حالت چهارم اگر بخواهیم دیکشنری خودمان را تعریف کنیم، به این صورت عمل می‌کنیم؛‌ var languages_and_framework = ["C++" : "QT Creator", "PHP" : "Laravel"] print(languages_and_framework) /* ["PHP" : "Laravel", "C++" : "Qt Creator"] نکته در تمامی این مثال‌ها، وقتی داده‌ها را نمایش می‌دهیم، به صورت نامرتب نمایش داده خواهند شد! چرا که همان ابتدا گفتیم، دیکشنری‌ها، نامرتب هستند و این مورد در خروجی داده‌ها هم صِدق می‌کند. نحوه‌ی دسترسی به داده‌های ما می‌توانیم با استفاده کلید ( Key ) به داده‌های مرتبط با آن دسترسی داشته باشیم! به این صورت که شما نام کلیدی را که از قبل انتخاب کردید، در بین دو براکت به همراه اسم دیکشنری خود آورده و سپس علامت تعجب (‌ ! ) را نوشته تا بتوانید مقدار مورد نظر را در دسترس داشته باشید! حتمالا با خود فکر می‌کنید که چرا علامت تعجب؟! اگر از جلسات قبل به خاطر داشته باشید، درمورد متغییر‌های آپشِنال ( Optionals ) صحبت کردیم و گفتیم که برای دسترسی به مقادیر این نوع متغییر‌ها باید از علامت ! استفاده کنیم. در دیکشنری‌ها هم همین موضوع برقرار است و شما برای استفاده از داده‌های آن باید آن‌ها را از حالت آپشنال خارج کنید. به این مثال دقت کنید؛ let _name_and_age : [String : UInt] = ["Mohammad" : 20, "Hamed" : 30] print(_name_and_age["Mohammad"]!) // 20 اگر علامت ! را ننویسید، با خطای کامپایلر مواجه خواهید شد. به همین صورت تا هر چند مقدار را که می‌خواهید می‌توانید به آن دسترسی داشته باشید. دقت کنید که اگر بخواهید یک مقدار خاص را در یک متغییر جداگانه ذخیره کنید، نیازی به علامت ! نخواهید داشت؛ let _name_and_age : [String : UInt] = ["Mohammad" : 20, "Hamed" : 30] let _age = _name_and_age["Mohammad"] print(_age["Mohammad"]!) // 20 اگر بخواهید متغییری که جداگانه تعریف کردید، نمایش دهید؛ آن موقع باید حتما از علامت تعجب ( ! ) استفاده کنید. اضافه کردن یک مقدار برای اضافه کردن یک مقدار، به همان صورتی که در بالا ( تکی اضافه کردن ) تعریف کردیم، استفاده می‌کنیم؛‌ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] numbers[40] = 50 print(numbers) /* [20 : 30, 10 : 20, 30 : 40, 40 : 50] */ بروز‌رسانی یک مقدار اگر بخواهیم داده‌های خود را به روز‌رسانی ( Update ) کنیم، کافیست کلید را آورده و در مقابل، مقدار را اضافه کنیم؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] numbers[40] = 50 numbers[10] = 100 print(numbers) /* [20 : 30, 10 : 100, 30 : 40, 40 : 50] */ همان‌طور که مشاهده می‌کنید، کلید ما در این بروز‌رسانی، ۱۰ است است و مقدار ۱۰۰ را به آن اختصاص داده‌ایم! پس دیگر خبری از مقدار ۲۰ نخواهد بود. هم‌چنین شما می‌توانید از متد updateValue از کلاس دیکشنری استفاده کنید. این متد، علاوه بر این‌که مقدار فعلی از یک کلید را برمی‌گرداند، همزمان، مقدار جدید را در همان کلید قرار خواهد داد. این متد دو آرگومان ( Argumant ) دریافت می‌کند که به شرح زیر است؛ اولین آرگومان، مقدار جدید است. دومین آرگومان، کلید است. مقدار برگشتی که از این متد، آپشنال خواهد بود! به این مثال دقت کنید؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] numbers[40] = 50 numbers[10] = 100 if old_number = numbers.updateValue(200, forkey: 20){ print("Old the number : \(old_number)") // Old the number : 30 } print(numbers) /* [20 : 200, 10 : 100, 30 : 40, 40 : 50] */ در قطعه کد بالا مشاهده می‌کنید که از یک شرط استفاده کردیم و مقدار برگشتی از متد updateValue را به متغییر old_number اختصاص داده‌ایم. این مقدار از کلید آن یعنی forkey: 20 گرفته شده است. هنگام چاپ مقدار old_number نیاز به قرار دادن علامت تعجب ( ! ) نیست! این‌کار در همان‌ابتدا در شرط انجام شده است. و در نهایت، در خروجی نهایی کل دیکشنری همان‌طور که می‌بینید، مقدار ۲۰۰ به کلید ۲۰ اختصاص داده شده است. اگر کلید که شما در آرگومان دوم داده باشید، وجود نداشته باشد، پیغام Not Exit و دیکشنری نمایش داده می‌شود، بدون این‌که مقداری حذف شده باشد‌. حذف کلید و مقدار اگر بخواهید کلید و مقدار خود را در حذف کنید، از کلمه‌ی کلید nil می‌توانید استفاده کنید؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] numbers[30] = nil print(numbers) /* [20 : 30, 10 : 20] */ مشاهده می‌کنید که کلید ۳۰ و مقدار ۴۰ هر دو حذف شدند. شاید با خودتان بگوید چرا کلید هم حذف شده است؟ به این دلیل که اگر مقداری برای کلید نباشد، خود کلید هم حذف خواهد شد؛ چون مقداری ندارد. شما می‌توانید از متد removeValue نیز استفاده کنید! این متد یک آرگومان گرفته و کلید/مقدار را حذف می‌کند. آرگومانی که این متد دریافت می‌کند، کلید است و مقدار برگشتی آن، مقدار حذف‌شده و به صورت آپشنال است ( اگر کلید که شما در آرگومان دوم داده باشید، وجود نداشته باشد، پیغام Not Exit به همراه خود دیکشنری نمایش داده می‌شود. ) به این مثال دقت کنید؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] if remove_value = numbers.removeValue(forkey: 10){ print("Removed value : \(remove_value)") // Removed value : 20 } print(numbers) /* [20 : 30, 30 : 40] */ همان‌طور که مشاهده می‌کنید، مقدار ۲۰ نمایش داده شده که درواقع مقدار حذف شده است. و در آخر هم کل دیکشنری را نمایش می‌دهیم که کلید ۱۰ و مقدار ۲۰ حذف شده‌اند. همچنین شما می‌توانید با استفاده از متد removeAll همه‌ی داده‌های دیکشنری را حذف کنید! دقت کنید که فقط داده‌های آن حذف خواهند شد نه خود دیکشنری! به این مثال دقت کنید؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] numbers.removeAll() print(numbers) // [:] همان‌طور که مشاهده کردید، فقط داده‌ها حذف شدند و خود دیکشنری هنوز در برنامه‌ی ما وجود دارد؛ بنابراین در ادامه می‌توانید داده‌های خود را اضافه کنید. گردش در دیکشنری ( Iterating over a dictionary ) شما می‌توانید با استفاده از حلقه‌ی for کلید‌ها و مقدار‌ها را دریافت کنید! هر کدام از این آیتم‌ها ( کلید/مقدار ) یک تاپِل هستند. به این مثال دقت کنید تا بهتر این موضوع را متوجه شوید؛‌ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] for (key, value) in numbers{ print("Key : \(key) and value : \(value)") } /* Key : 10 and value : 20 Key : 20 and value : 30 Key : 30 and value : 40 */ در قطعه کد بالا شما در حلقه‌ی for در بین دو پرانتز () به دلخواه دو نام انتخاب کرده که نشان از کلید و مقدار است و در نهایت کلمه‌ی کلید in را نوشته و دیکشنری را می‌نویسید. به دست آوردن کلید‌ها اگر بخواهید فقط و فقط کلید‌های یک دیکشنری را به دست آورید، می‌توانید با استفاده از ویژگی ( Properties‌ ) به نام keys در حلقه‌ی for یا به تنهایی استفاده کنید. به این مثال دقت کنید؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] for key in numbers.keys{ print("Key : \(key)") } /* Key : 10 Key : 20 Key : 30 */ // Or print("Keys : \(numbers.keys)") // Output: Keys : [10,20,30] به دست آوردن مقدار‌ها در مقابل شما می‌توانید با استفاده از ویژگی values فقط و فقط به مقادیر دسترسی داشته باشید. به این مثال دقت کنید؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] for value in numbers.values{ print("Value : \(value)") } /* Value : 20 Value : 30 Value : 40 */ // Or print("Values : \(numbers.values)") // Output: Values : [20,30,40] مرتب‌سازی همان‌طور که می‌دانید و همان‌ ابتدا هم گفتیم، دیکشنری‌ها نوعی هستند که نامرتب‌‌اند! یعن داده‌ها را به صورت تصادفی ( Random ) نمایش می‌دهند. اما ما در ادامه مثالی را ذکر خواهیم کرد که شما می‌توانید، هم براساس کلید و هم مقدار، اقدام به مرتب‌سازی داده‌ها کنید. مرتب‌سازی بر اساس مقدار در این حالت ما با استفاده از ویژگی values و سپس متد sorted که همراه خودش دارد، براساس مقدار فقط داده‌ها را مرتب می‌کنیم؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] for sorted_by_value in numbers.values.sorted{ print("Sorted by value : \(sorted_by_value)") } /* Sorted by value : 20 Sorted by value : 30 Sorted by value : 40 */ نکته استفاده از دو حالت بالا صحیح است و اگر شما دو ویژگی values و keys را نیاورید، و فقط متد sorted را به همراه نام دیکشنری بنویسید، اشتباه ‌خواهد بود و از طرف کامپایلر خطا دریافت می‌کنید. به مثال زیر که اشتباه است دقت کنید؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] print(numbers.sorted()) // Error همان‌طور که مشاهده می‌کنید، استفاده از متد بدون ذکر یک از دو ویژگی values و keys از نظر کامپایلر بی‌معنی است و در نتیجه خطا را صادر می‌کند. دسترسی به تعدا اعضای دیکشنری برای این‌که بتوانید به تعداد اعضای یک دیکشنری دسترسی داشته باشید، از ویژگی count‌ می‌توانید استفاده کنید؛ var numbers : [Int : Int] = [10 : 20, 20 : 30, 30 : 40] print("Count the numbers : \(numbers.count)") // Count the numbers : 3 دقت کنید که منظور از تعدا اعضا، هم کلید و هم مقدار نیست! بلکه یعنی یک کلید و یک مقدار می‌شود یک عضو! در قطعه کد بالا هم مشاهده می‌کنید که ما سه عضو داریم که در خروجی نمایش داده شده است. بررسی خالی بودن یا نبودن دیکشنری با استفاده از ویژگی isEmpty شما می‌توانید، بررسی کنید که آیا دیکشنریتان خالی است یا نه؟! به این مثال دقت کنید؛ var numbers : [Int : Int] = [:] if numbers.isEmpty{ print("Dictionary is empty!") // Yes, it is Empty } else { print("Dictionary is not empty!") } با استفاده از [:] می‌توانید در همان ابتدا اعلام کنید که دیکشنری شما خالی است. همان‌طور که در خروجی هم می‌بینید، خروجی برابر است با Dictionary is empty است. امیدواریم که این جلسه مورد رضایت شما قرار گرفته باشد.
  2. 1 امتیاز
    پاسخ به این سوأل صرفاً از نظر نوع زبان کافی نیست و شاید منطقی نباشد. و چون ساختار و قوانین تحت چهارچوب مشخصی برای این موضوع نداریم، از نظر من دلایل بسیاری وجود دارد که بر روی قیمت‌گذاری می‌تواند تأثیرگذار باشد که به آن‌ها اشاره می‌کنم: تجربه و کیفیت خدماتِ قابل ارائه‌ی فرد یا شرکت توسعه‌دهنده جهت انجام آن اینکه شخص یا شرکت مربوطه بتواند تضمین کند یا آسودگی خاطر را به مشتری بدهد که پروژه‌ی آن در زمان مشخص با نتیجه‌ی قابل قبول ارائه خواهد شد بسیار مهم است، قطعاً اطمینان خاطر و جلوگیری از احتمالات دوباره‌کاری و نا رضایتی خودش ارزشمند خواهد بود که ممکن است در هزینه‌ی نهایی پروژه موثر باشد. تضامین و خدمات پس از فروش «پشتیبانی، به‌روز‌رسانی و غیره» هرچند پشتیبانی و به‌روزرسانی محصولات نرم‌افزاری یکی از مراحل توسعه و چرخه‌ی نرم‌افزار است، اما در دسترس بودن و تضمین پشتیبانی از سمت توسعه‌دهنده قطعاً در هزینه‌های آن نسبت به دیگر موارد متفاوت خواهد بود. نوع قرارداد و مذاکراتی که ممکن است طرفین در قبال تعهد به آن‌ها هزینه‌هایی را اضافه کند معمولاً در قرارداد‌های طرفین به نکاتی اشاره می‌شود، مانند: در دسترس بودن منبع‌کد «سورس‌کد» و یا مستند سازی غیر معمول و اختصاصی که حتماً در قیمت نهایی یک محصول و پروژه موثر خواهد بود. محدودیت‌ها و دلایل قانع کننده برای انتخاب یک ابزار و نیاز به دانش و مهارت‌های تخصصی ممکن است پروژه‌ای که به شما پیشنهاد می‌شود، با یک سری محدودیت‌های فنی بر اساس نوع زبان، مهارت و بستر‌های پیاده‌سازی مواجه باشد که با توجه به ارائه‌ی راه‌کار‌های مناسب توسط متخصص «توسعه‌دهنده» که واقعاً نیاز به تجربه و دانش در حل آن است وابسته خواهد بود. در چنین حالت‌های ارزش حل مسائل می‌تواند در خود پروژه تأثیر‌ بگذارد. در نهایت بعد از بررسی موارد این چنینی که من تنها به برخی از آن‌ها اشاره کردم، می‌توانید به خروجی‌ها و نتایج حاصل از خود ابزار که در اینجا «++C» است اشاره کرده و مشتری را نسبت به آن قانع کنید. برای مثال، ویژگیِ چند-سکویی خود به تنهایی یک مزیت بسیار بزرگ است که می‌تواند در حذف هزینه‌های احتمالی مانند بازنویسی در زمان توسعه و به‌روز رسانی در قالب سکو‌های مختلف موثر باشد. نوع مذاکره در ساخت و توسعه در قالب زمان مشخص برای ساده‌سازی مسئله و حل باید‌ها و نباید‌ها نیز مشخص سازی یک نرخ یا رنج قیمت برای کار بر روی پروژه می‌تواند موثر باشد. برای مثال، بر اساس تعداد ساعت و زمان مشخص در روز می‌توانید یک محاسبه‌ی مشخصی برای مشتری خود انتقال دهید تا هم زمان تحویل و هم مدت زمات مورد نیاز برای توسعه را بداند. درباره‌ی همین موضوع چند-سکویی که تنها یک ویژگی از مزایای سی‌پلاس‌پلاس است مثالی بزنم: فرض کنید قرار است مشتری یک نرم‌افزار تحت موبایل از شما درخواست کند، در این صورت اگر قرار باشد منطقی مذاکره کنید، بهتر است مشتری را متوجه این سازید که برای ساخت یک اپلیکیشن در سکو‌های مختلف مانند iOS، Android و غیره نیاز به تخصص، زمان و هزینه‌های جدا از هم است. اما اگر شما به عنوانی توسعه‌‌دهنده‌ی تمام عیار فول‌اِستک هستید، می‌توانید مشتری را قانع کنید که صرفاً با یکپارچه‌سازی کد‌های توسعه و ساختار بهینه‌ی برنامه‌های نوشته شده‌ی تحت سی++ از صرف هزینه‌های احتمالی جهت توسعه‌ جلوگیری می‌کنید و حتی در آینده نیازی نیست هزینه‌های اضافه بر مشتری تحمیل کنید. در این رابطه باید به یک هزینه‌ی قابل قبول همراه با حفظ ارزش‌های وارده را مطرح کنید. برای مثال، اگر قرار است یک اپلیکیشن برای دو پلتفرم مختلف توسعه یابد، اگر قیمتی بابت یک نرم‌افزار در دو سکوی مختلف استعلام و یا تخمین زده شده باشد، بهتر است شما با در نظر گرفتن نصف و یا حد‌اکثر دو سوم آن همان کارها را با حفظ ارزش‌های فنی و کاربری مشتری انجام دهید. بر اساس چنین مواردی نیازی به افزایش یا کاهش هزینه‌ها در یک پلتفرم وجود ندارد چرا که تنها کاری که انجام خواهید داد هم‌گردانی «کامپایل» کد‌ها بر روی پلتفرم دیگر خواهد بود.
این صفحه از پرچمداران بر اساس منطقه زمانی تهران/GMT+03:30 می باشد
×
×
  • جدید...