---
title: "ثلاث مقارنات تفعلها المكتبة القياسية عنك"
description: "إيجاد أول مطابق، والترتيب بأكثر من مفتاح، وفحص فهرس في مدًى. الصيغة المكتوبة باليد أطول في الثلاث، وأبطأ في اثنتين منها."
author: "Omar Albeik"
date: 2019-12-16
type: note
topics: [swift, software, engineering]
language: ar
reading_time_minutes: 2
canonical_url: https://omaralbeik.com/ar/blog/let-the-standard-library-compare
translation_url: https://omaralbeik.com/en/blog/let-the-standard-library-compare
source_url: https://omaralbeik.com/ar/blog/let-the-standard-library-compare.md
---

# ثلاث مقارنات تفعلها المكتبة القياسية عنك

ثلاثة أشياء أعيد كتابتها بيدي، ثم أجدها في المكتبة القياسية موجودةً أصلًا. لا
جامع بينها إلا أنّ الصيغة الأطول في كلٍّ منها هي التي أمدّ يدي إليها أولًا.

## إيجاد أوّل مطابق

```swift
let firstSeven = numbers.filter { $0 == 7 }.first
```

يمرّ `filter` على كل عنصر ويحجز مصفوفةً تحمل المطابقات، ثم يأخذ `first` واحدًا
ويُهمَل الباقي. ففي مصفوفةٍ من مئة عنصرٍ والمطلوب في الموضع الثاني، تلك ثمانٍ
وتسعون مقارنةً لا حاجة إليها.

```swift
let firstSeven = numbers.first { $0 == 7 }
```

يقف `first(where:)` عند أول مطابق ولا يحجز شيئًا. وكلاهما O(n) في أسوأ الحالات،
فليست هذه حجّةً في التعقيد — إنّما الفرق أنّ كلفة الأول تتبع موضع المطابق، وكلفة
الثاني تتبع طول المتتالية.

## الترتيب بأكثر من مفتاح

رتّب جهات الاتصال بالكنية، ثم بالاسم داخل كل عائلة. وكتابتها باليد سلسلة
مقارنات تتوقف على فحص تساوٍ يسهل الخطأ فيه:

```swift
if lhs.surname != rhs.surname {
  return lhs.surname < rhs.surname
}
return lhs.name < rhs.name
```

والصفوف tuples المكوّنة من عناصر `Comparable` هي نفسها `Comparable`، ومقارنتها
معجميّة — وهي بعينها القاعدة التي كنت تكتبها:

```swift
extension Person: Comparable {
  static func < (lhs: Person, rhs: Person) -> Bool {
    (lhs.surname, lhs.name) < (rhs.surname, rhs.name)
  }
}
```

وإضافة مفتاحٍ ثالث هي إضافة عنصرٍ ثالث إلى كل صفّ. أما الصيغة الأطول فتزيد
أربعة أسطر، ومعها احتمال جديد لمقارنة الطرف الخطأ.

## فحص فهرسٍ في مدًى

```swift
if index >= 0 && index < items.count {
```

مقارنتان وافتراض: أنّ الفهارس تبدأ من الصفر، وهذا صحيحٌ في `Array` وغير صحيحٍ
في `ArraySlice`، فإنّ فهارسها موروثةٌ من المصفوفة التي اقتُطعت منها. و‏`~=` هو
عامل مطابقة الأنماط، الذي يستعمله `switch` في `case 0..<10`، ويمكن استدعاؤه
مباشرة:

```swift
if 0..<items.count ~= index {
```

وهذا أقصر، لكنّه الافتراض نفسه — أنّ البداية صفر — في حروفٍ أقلّ، ولا يصلح
الشريحة. أما `items.indices.contains(index)` فيصلحها، لأنّه يسأل المجموعة عن
حدودها بدل أن يبنيها:

```swift
if items.indices.contains(index) {
```

الثلاث كلّها مواضع توفّر فيها المكتبة القياسية العملية جاهزة، وتبقى الصيغة
الأطول عادةً لا ضرورة.
