🎯 Рекомендуемые коллекции
Балансированные коллекции примеров кода из различных категорий, которые вы можете исследовать
Структуры Данных macOS Objective-C - Примеры
Примеры структур данных macOS Objective-C включая массивы, словари, множества, пользовательские классы и алгоритмы
💻 Массивы и Коллекции objectivec
🟢 simple
⭐⭐
Работа с NSArray и NSMutableArray для основных операций с массивами
⏱️ 20 min
🏷️ objectivec, macos, data structures, arrays
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C Arrays and Collections Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. NSArray Basics
@interface ArrayBasics : NSObject
+ (void)demonstrateImmutableArray {
NSLog(@"--- Immutable Array ---");
// Create array
NSArray *fruits = @[@"Apple", @"Banana", @"Cherry", @"Date"];
NSLog(@"Fruits: %@", fruits);
NSLog(@"Count: %lu", (unsigned long)fruits.count);
// Access elements
NSString *first = fruits.firstObject;
NSString *last = fruits.lastObject;
NSString *second = fruits[1];
NSLog(@"First: %@", first);
NSLog(@"Last: %@", last);
NSLog(@"Second: %@", second);
// Check contains
BOOL contains = [fruits containsObject:@"Banana"];
NSLog(@"Contains Banana: %@", contains ? @"YES" : @"NO");
// Find index
NSUInteger index = [fruits indexOfObject:@"Cherry"];
NSLog(@"Index of Cherry: %lu", (unsigned long)index);
// Enumerate
NSLog(@"Enumerating:");
[fruits enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL *stop) {
NSLog(@" %lu: %@", (unsigned long)idx, obj);
}];
// Filter
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"length > 5"];
NSArray *longNames = [fruits filteredArrayUsingPredicate:predicate];
NSLog(@"Long names (>5 chars): %@", longNames);
// Sort
NSArray *sorted = [fruits sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"Sorted: %@", sorted);
// Subarray
NSRange range = NSMakeRange(1, 2);
NSArray *subarray = [fruits subarrayWithRange:range];
NSLog(@"Subarray (1-2): %@", subarray);
// Join
NSString *joined = [fruits componentsJoinedByString:@", "];
NSLog(@"Joined: %@", joined);
}
+ (void)demonstrateMutableArray {
NSLog(@"\n--- Mutable Array ---");
// Create mutable array
NSMutableArray *numbers = [NSMutableArray array];
// Add objects
[numbers addObject:@(1)];
[numbers addObject:@(2)];
[numbers addObject:@(3)];
NSLog(@"Numbers: %@", numbers);
// Insert at index
[numbers insertObject:@(100) atIndex:0];
NSLog(@"After insert at 0: %@", numbers);
// Replace object
numbers[1] = @(200);
NSLog(@"After replace index 1: %@", numbers);
// Remove object
[numbers removeObject:@(3)];
NSLog(@"After remove 3: %@", numbers);
// Remove at index
[numbers removeObjectAtIndex:0];
NSLog(@"After remove at 0: %@", numbers);
// Add multiple objects
[numbers addObjectsFromArray:@[@(4), @(5), @(6)]];
NSLog(@"After add multiple: %@", numbers);
// Remove all
[numbers removeAllObjects];
NSLog(@"After remove all: %@", numbers);
// Populate from 0 to 9
for (NSInteger i = 0; i < 10; i++) {
[numbers addObject:@(i)];
}
NSLog(@"Populated: %@", numbers);
// Reverse
NSArray *reversed = [[numbers reverseObjectEnumerator] allObjects];
NSLog(@"Reversed: %@", reversed);
}
@end
// MARK: - 2. Array Operations
@interface ArrayOperations : NSObject
+ (NSArray *)map:(NSArray *)array usingBlock:(id (^)(id obj))block {
NSMutableArray *result = [NSMutableArray arrayWithCapacity:array.count];
for (id obj in array) {
[result addObject:block(obj)];
}
return [result copy];
}
+ (NSArray *)filter:(NSArray *)array usingBlock:(BOOL (^)(id obj))block {
NSMutableArray *result = [NSMutableArray array];
for (id obj in array) {
if (block(obj)) {
[result addObject:obj];
}
}
return [result copy];
}
+ (id)reduce:(NSArray *)array initial:(id)initial usingBlock:(id (^)(id acc, id obj))block {
id accumulator = initial;
for (id obj in array) {
accumulator = block(accumulator, obj);
}
return accumulator;
}
+ (void)demonstrateOperations {
NSLog(@"\n--- Array Operations ---");
NSArray *numbers = @[@(1), @(2), @(3), @(4), @(5)];
// Map: square each number
NSArray *squared = [self map:numbers usingBlock:^NSNumber *(NSNumber *obj) {
NSInteger value = [obj integerValue];
return @(value * value);
}];
NSLog(@"Original: %@", numbers);
NSLog(@"Squared: %@", squared);
// Filter: even numbers
NSArray *evens = [self filter:numbers usingBlock:^BOOL(NSNumber *obj) {
return [obj integerValue] % 2 == 0;
}];
NSLog(@"Evens: %@", evens);
// Reduce: sum
NSNumber *sum = [self reduce:numbers initial:@(0) usingBlock:^NSNumber *(NSNumber *acc, NSNumber *obj) {
return @([acc integerValue] + [obj integerValue]);
}];
NSLog(@"Sum: %@", sum);
// Chaining: map -> filter -> reduce
NSNumber *result = [self reduce:[self filter:[self map:numbers usingBlock:^NSNumber *(NSNumber *obj) {
return @(pow([obj integerValue], 2));
}] usingBlock:^BOOL(NSNumber *obj) {
return [obj integerValue] > 10;
}] initial:@(0) usingBlock:^NSNumber *(NSNumber *acc, NSNumber *obj) {
return @([acc integerValue] + [obj integerValue]);
}];
NSLog(@"Squared > 10, sum: %@", result);
}
@end
// MARK: - 3. Searching and Sorting
@interface SearchSort : NSObject
+ (void)demonstrateSearch {
NSLog(@"\n--- Searching ---");
NSArray *names = @[@"Alice", @"Bob", @"Charlie", @"David", @"Eve"];
// Binary search (requires sorted array)
NSArray *sortedNames = [names sortedArrayUsingSelector:@selector(compare:)];
NSUInteger index = [sortedNames indexOfObject:@"Charlie"
inSortedRange:NSMakeRange(0, sortedNames.count)
options:NSBinarySearchingFirstEqual
usingComparator:^(id obj1, id obj2) {
return [obj1 compare:obj2];
}];
if (index != NSNotFound) {
NSLog(@"Found 'Charlie' at index: %lu", (unsigned long)index);
}
// Find all matches
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH 'A'"];
NSArray *aNames = [names filteredArrayUsingPredicate:predicate];
NSLog(@"Starting with 'A': %@", aNames);
}
+ (void)demonstrateSort {
NSLog(@"\n--- Sorting ---");
// Simple sort
NSArray *unsorted = @[@"delta", @"alpha", @"charlie", @"bravo"];
NSArray *sorted = [unsorted sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"Alphabetical: %@", sorted);
// Sort with comparator
NSArray *numbers = @[@(5), @(1), @(9), @(3), @(7)];
NSArray *numbersDesc = [numbers sortedArrayUsingComparator:^NSComparisonResult(NSNumber *obj1, NSNumber *obj2) {
return [obj2 compare:obj1]; // Descending
}];
NSLog(@"Numbers descending: %@", numbersDesc);
// Sort strings by length
NSArray *words = @[@"apple", @"pie", @"a", @"banana"];
NSArray *byLength = [words sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
if (obj1.length < obj2.length) return NSOrderedAscending;
if (obj1.length > obj2.length) return NSOrderedDescending;
return NSOrderedSame;
}];
NSLog(@"By length: %@", byLength);
// Sort custom objects
NSArray *people = @[
@{@"name": @"Alice", @"age": @(30)},
@{@"name": @"Bob", @"age": @(25)},
@{@"name": @"Charlie", @"age": @(35)}
];
NSSortDescriptor *ageDesc = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
NSArray *byAge = [people sortedArrayUsingDescriptors:@[ageDesc]];
NSLog(@"Sorted by age:");
for (NSDictionary *person in byAge) {
NSLog(@" %@: %@", person[@"name"], person[@"age"]);
}
}
@end
// MARK: - 4. Two-Dimensional Arrays
@interface Matrix2D : NSObject
+ (NSArray *)createMatrixWithRows:(NSUInteger)rows columns:(NSUInteger)cols {
NSMutableArray *matrix = [NSMutableArray arrayWithCapacity:rows];
for (NSUInteger i = 0; i < rows; i++) {
NSMutableArray *row = [NSMutableArray arrayWithCapacity:cols];
for (NSUInteger j = 0; j < cols; j++) {
[row addObject:@(i * cols + j)];
}
[matrix addObject:[row copy]];
}
return [matrix copy];
}
+ (void)printMatrix:(NSArray *)matrix {
NSLog(@"Matrix (%lu x %lu):", (unsigned long)matrix.count, (unsigned long)[matrix[0] count]);
for (NSArray *row in matrix) {
NSLog(@" %@", row);
}
}
+ (NSArray *)transposeMatrix:(NSArray *)matrix {
NSUInteger rows = matrix.count;
NSUInteger cols = [matrix[0] count];
NSMutableArray *result = [NSMutableArray arrayWithCapacity:cols];
for (NSUInteger j = 0; j < cols; j++) {
NSMutableArray *newRow = [NSMutableArray arrayWithCapacity:rows];
for (NSUInteger i = 0; i < rows; i++) {
[newRow addObject:matrix[i][j]];
}
[result addObject:[newRow copy]];
}
return [result copy];
}
+ (void)demonstrateMatrix {
NSLog(@"\n--- 2D Matrix ---");
NSArray *matrix = [self createMatrixWithRows:3 columns:4];
[self printMatrix:matrix];
NSLog(@"\nTransposed:");
NSArray *transposed = [self transposeMatrix:matrix];
[self printMatrix:transposed];
// Access element
NSNumber *element = matrix[1][2];
NSLog(@"Element at [1][2]: %@", element);
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Arrays Examples ===\n");
// 1. Immutable array
[ArrayBasics demonstrateImmutableArray];
// 2. Mutable array
[ArrayBasics demonstrateMutableArray];
// 3. Operations
[ArrayOperations demonstrateOperations];
// 4. Search
[SearchSort demonstrateSearch];
// 5. Sort
[SearchSort demonstrateSort];
// 6. Matrix
[Matrix2D demonstrateMatrix];
NSLog(@"\n=== Arrays Examples Completed ===");
}
return 0;
}
💻 Словари и Отображения objectivec
🟢 simple
⭐⭐
Использовать NSDictionary и NSMutableDictionary для хранения и поиска ключ-значение
⏱️ 20 min
🏷️ objectivec, macos, data structures, dictionaries
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C Dictionaries Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. NSDictionary Basics
@interface DictionaryBasics : NSObject
+ (void)demonstrateImmutableDictionary {
NSLog(@"--- Immutable Dictionary ---");
// Create dictionary
NSDictionary *person = @{
@"name": @"Alice",
@"age": @(30),
@"city": @"San Francisco",
@"email": @"[email protected]"
};
NSLog(@"Person: %@", person);
// Access values
NSString *name = person[@"name"];
NSNumber *age = person[@"age"];
NSString *email = [person objectForKey:@"email"];
NSLog(@"Name: %@", name);
NSLog(@"Age: %@", age);
NSLog(@"Email: %@", email);
// Get all keys and values
NSArray *keys = person.allKeys;
NSArray *values = person.allValues;
NSLog(@"Keys: %@", keys);
NSLog(@"Values: %@", values);
// Count
NSLog(@"Count: %lu", (unsigned long)person.count);
// Check for key
BOOL hasName = [person objectForKey:@"name"] != nil;
BOOL hasAddress = [person objectForKey:@"address"] != nil;
NSLog(@"Has 'name': %@", hasName ? @"YES" : @"NO");
NSLog(@"Has 'address': %@", hasAddress ? @"YES" : @"NO");
// Enumerate
NSLog(@"Enumerating keys and values:");
[person enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
NSLog(@" %@: %@", key, value);
}];
// Filter keys
NSArray *nameKeys = [person keysOfEntriesPassingTest:^BOOL(NSString *key, id value, BOOL *stop) {
return [key hasPrefix:@"n"];
}];
NSLog(@"Keys starting with 'n': %@", nameKeys);
// Dictionary to array
NSArray *keyValuePairs = [person allKeys];
NSLog(@"As array: %@", keyValuePairs);
}
+ (void)demonstrateMutableDictionary {
NSLog(@"\n--- Mutable Dictionary ---");
// Create mutable dictionary
NSMutableDictionary *stats = [NSMutableDictionary dictionary];
// Add entries
stats[@"wins"] = @(10);
stats[@"losses"] = @(5);
stats[@"draws"] = @(2);
NSLog(@"Stats: %@", stats);
// Update value
stats[@"wins"] = @(11);
NSLog(@"After update wins: %@", stats);
// Remove entry
[stats removeObjectForKey:@"draws"];
NSLog(@"After remove draws: %@", stats);
// Add multiple entries
[stats addEntriesFromDictionary:@{
@"goals": @(25),
@"assists": @(12)
}];
NSLog(@"After add multiple: %@", stats);
// Remove all
[stats removeAllObjects];
NSLog(@"After remove all: %@", stats);
// Populate dynamically
for (NSInteger i = 0; i < 5; i++) {
NSString *key = [NSString stringWithFormat:@"key%ld", (long)i];
stats[key] = @(i * 10);
}
NSLog(@"Populated: %@", stats);
}
@end
// MARK: - 2. Nested Dictionaries
@interface NestedDictionaries : NSObject
+ (void)demonstrateNested {
NSLog(@"\n--- Nested Dictionaries ---");
// Company structure
NSDictionary *company = @{
@"name": @"TechCorp",
@"founded": @(2010),
@"departments": @{
@"engineering": @{
@"head": @"Alice",
@"count": @(50),
@"budget": @(1000000)
},
@"marketing": @{
@"head": @"Bob",
@"count": @(20),
@"budget": @(500000)
},
@"sales": @{
@"head": @"Charlie",
@"count": @(30),
@"budget": @(750000)
}
}
};
NSLog(@"Company: %@", company[@"name"]);
// Access nested values
NSDictionary *engineering = company[@"departments"][@"engineering"];
NSLog(@"Engineering head: %@", engineering[@"head"]);
NSLog(@"Engineering count: %@", engineering[@"count"]);
// Enumerate departments
NSDictionary *departments = company[@"departments"];
NSLog(@"\nDepartments:");
[departments enumerateKeysAndObjectsUsingBlock:^(NSString *deptName, NSDictionary *info, BOOL *stop) {
NSLog(@" %@ - Head: %@, Count: %@", deptName, info[@"head"], info[@"count"]);
}];
// Calculate total budget
__block double totalBudget = 0;
[departments enumerateKeysAndObjectsUsingBlock:^(NSString *deptName, NSDictionary *info, BOOL *stop) {
totalBudget += [info[@"budget"] doubleValue];
}];
NSLog(@"\nTotal budget: $%.0f", totalBudget);
}
@end
// MARK: - 3. Dictionary Operations
@interface DictionaryOperations : NSObject
+ (NSDictionary *)merge:(NSDictionary *)dict1 with:(NSDictionary *)dict2 {
NSMutableDictionary *result = [dict1 mutableCopy];
[result addEntriesFromDictionary:dict2];
return [result copy];
}
+ (NSDictionary *)mapValues:(NSDictionary *)dict usingBlock:(id (^)(id value))block {
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithCapacity:dict.count];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
result[key] = block(value);
}];
return [result copy];
}
+ (NSDictionary *)filterKeys:(NSDictionary *)dict usingBlock:(BOOL (^)(id key))block {
NSMutableDictionary *result = [NSMutableDictionary dictionary];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
if (block(key)) {
result[key] = value;
}
}];
return [result copy];
}
+ (void)demonstrateOperations {
NSLog(@"\n--- Dictionary Operations ---");
// Merge
NSDictionary *defaults = @{
@"theme": @"light",
@"fontSize": @(14),
@"showSidebar": @(YES)
};
NSDictionary *userSettings = @{
@"theme": @"dark",
@"fontSize": @(16)
};
NSDictionary *merged = [self merge:defaults with:userSettings];
NSLog(@"Merged: %@", merged);
// Map values
NSDictionary *prices = @{
@"item1": @(10),
@"item2": @(20),
@"item3": @(30)
};
NSDictionary *discounted = [self mapValues:prices usingBlock:^NSNumber *(NSNumber *price) {
return @([price doubleValue] * 0.9);
}];
NSLog(@"Original: %@", prices);
NSLog(@"Discounted (10%%): %@", discounted);
// Filter keys
NSDictionary *userData = @{
@"username": @"alice",
@"password": @"secret123",
@"email": @"[email protected]",
@"age": @(30)
};
NSDictionary *publicData = [self filterKeys:userData usingBlock:^BOOL(NSString *key) {
return ![key isEqualToString:@"password"];
}];
NSLog(@"All data: %@", userData);
NSLog(@"Public data: %@", publicData);
}
@end
// MARK: - 4. Dictionary as Cache
@interface Cache : NSObject
@property (nonatomic, strong) NSMutableDictionary *storage;
@property (nonatomic, strong) NSMutableDictionary *timestamps;
@property (nonatomic, assign) NSTimeInterval ttl;
- (instancetype)initWithTTL:(NSTimeInterval)ttl;
- (void)setObject:(id)obj forKey:(NSString *)key;
- (id)objectForKey:(NSString *)key;
- (void)removeObjectForKey:(NSString *)key;
- (void)removeExpiredObjects;
- (void)clear;
@end
@implementation Cache
- (instancetype)initWithTTL:(NSTimeInterval)ttl {
self = [super init];
if (self) {
_storage = [NSMutableDictionary dictionary];
_timestamps = [NSMutableDictionary dictionary];
_ttl = ttl;
}
return self;
}
- (void)setObject:(id)obj forKey:(NSString *)key {
self.storage[key] = obj;
self.timestamps[key] = [NSDate date];
}
- (id)objectForKey:(NSString *)key {
NSDate *timestamp = self.timestamps[key];
if (!timestamp) {
return nil;
}
NSTimeInterval age = [[NSDate date] timeIntervalSinceDate:timestamp];
if (age > self.ttl) {
[self removeObjectForKey:key];
return nil;
}
return self.storage[key];
}
- (void)removeObjectForKey:(NSString *)key {
[self.storage removeObjectForKey:key];
[self.timestamps removeObjectForKey:key];
}
- (void)removeExpiredObjects {
NSDate *now = [NSDate date];
NSArray *keys = [self.timestamps allKeys];
for (NSString *key in keys) {
NSDate *timestamp = self.timestamps[key];
NSTimeInterval age = [now timeIntervalSinceDate:timestamp];
if (age > self.ttl) {
[self removeObjectForKey:key];
}
}
}
- (void)clear {
[self.storage removeAllObjects];
[self.timestamps removeAllObjects];
}
@end
@interface CacheDemo : NSObject
+ (void)demonstrateCache {
NSLog(@"\n--- Dictionary as Cache ---");
Cache *cache = [[Cache alloc] initWithTTL:5.0]; // 5 second TTL
// Add items
[cache setObject:@"Data 1" forKey:@"key1"];
[cache setObject:@"Data 2" forKey:@"key2"];
NSLog(@"Get key1: %@", [cache objectForKey:@"key1"]);
NSLog(@"Get key2: %@", [cache objectForKey:@"key2"]);
NSLog(@"Get key3: %@", [cache objectForKey:@"key3"]);
NSLog(@"\nWaiting 6 seconds...");
[NSThread sleepForTimeInterval:6.0];
NSLog(@"After expiry:");
NSLog(@"Get key1: %@", [cache objectForKey:@"key1"]);
NSLog(@"Get key2: %@", [cache objectForKey:@"key2"]);
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Dictionaries Examples ===\n");
// 1. Immutable
[DictionaryBasics demonstrateImmutableDictionary];
// 2. Mutable
[DictionaryBasics demonstrateMutableDictionary];
// 3. Nested
[NestedDictionaries demonstrateNested];
// 4. Operations
[DictionaryOperations demonstrateOperations];
// 5. Cache
[CacheDemo demonstrateCache];
NSLog(@"\n=== Dictionaries Examples Completed ===");
}
return 0;
}
💻 Множества и Уникальные Коллекции objectivec
🟢 simple
⭐⭐⭐
Использовать NSSet и NSMutableSet для хранения уникальных элементов и операций множеств
⏱️ 25 min
🏷️ objectivec, macos, data structures, sets
Prerequisites:
Objective-C basics, Foundation framework
// macOS Objective-C Sets Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. NSSet Basics
@interface SetBasics : NSObject
+ (void)demonstrateImmutableSet {
NSLog(@"--- Immutable Set ---");
// Create set
NSSet *fruits = [NSSet setWithObjects:@"Apple", @"Banana", @"Cherry", @"Apple", nil];
NSLog(@"Fruits: %@", fruits);
NSLog(@"Count: %lu", (unsigned long)fruits.count);
// Check contains
BOOL hasApple = [fruits containsObject:@"Apple"];
BOOL hasGrape = [fruits containsObject:@"Grape"];
NSLog(@"Has Apple: %@", hasApple ? @"YES" : @"NO");
NSLog(@"Has Grape: %@", hasGrape ? @"YES" : @"NO");
// Get any object
id anyObject = [fruits anyObject];
NSLog(@"Any object: %@", anyObject);
// Convert to array
NSArray *allObjects = [fruits allObjects];
NSLog(@"As array: %@", allObjects);
// Enumerate
NSLog(@"Enumerating:");
[fruits enumerateObjectsUsingBlock:^(NSString *obj, BOOL *stop) {
NSLog(@" %@", obj);
}];
}
+ (void)demonstrateMutableSet {
NSLog(@"\n--- Mutable Set ---");
// Create mutable set
NSMutableSet *numbers = [NSMutableSet set];
// Add objects
[numbers addObject:@(1)];
[numbers addObject:@(2)];
[numbers addObject:@(3)];
[numbers addObject:@(1)]; // Duplicate, won't be added
NSLog(@"Numbers: %@", numbers);
// Remove object
[numbers removeObject:@(2)];
NSLog(@"After remove 2: %@", numbers);
// Add multiple
[numbers addObjectsFromArray:@[@(4), @(5), @(6)]];
NSLog(@"After add multiple: %@", numbers);
// Remove all
[numbers removeAllObjects];
NSLog(@"After remove all: %@", numbers);
// Populate
for (NSInteger i = 0; i < 10; i++) {
[numbers addObject:@(i)];
}
NSLog(@"Populated: %@", numbers);
}
@end
// MARK: - 2. Set Operations
@interface SetOperations : NSObject
+ (NSSet *)unionOf:(NSSet *)set1 and:(NSSet *)set2 {
NSMutableSet *result = [set1 mutableCopy];
[result unionSet:set2];
return [result copy];
}
+ (NSSet *)intersectionOf:(NSSet *)set1 and:(NSSet *)set2 {
NSMutableSet *result = [set1 mutableCopy];
[result intersectSet:set2];
return [result copy];
}
+ (NSSet *)differenceOf:(NSSet *)set1 and:(NSSet *)set2 {
NSMutableSet *result = [set1 mutableCopy];
[result minusSet:set2];
return [result copy];
}
+ (BOOL)isSubset:(NSSet *)subset ofSet:(NSSet *)set {
return [set isSubsetOfSet:subset];
}
+ (void)demonstrateOperations {
NSLog(@"\n--- Set Operations ---");
NSSet *setA = [NSSet setWithObjects:@(1), @(2), @(3), @(4), @(5), nil];
NSSet *setB = [NSSet setWithObjects:@(4), @(5), @(6), @(7), @(8), nil];
NSLog(@"Set A: %@", setA);
NSLog(@"Set B: %@", setB);
// Union
NSSet *unionSet = [self unionOf:setA and:setB];
NSLog(@"Union (A ∪ B): %@", unionSet);
// Intersection
NSSet *intersection = [self intersectionOf:setA and:setB];
NSLog(@"Intersection (A ∩ B): %@", intersection);
// Difference
NSSet *difference = [self differenceOf:setA and:setB];
NSLog(@"Difference (A - B): %@", difference);
// Subset
NSSet *subset = [NSSet setWithObjects:@(1), @(2), nil];
BOOL isSubset = [self isSubset:subset ofSet:setA];
NSLog(@"Is {1, 2} subset of A: %@", isSubset ? @"YES" : @"NO");
// Predicate filter
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self > 3"];
NSSet *filtered = [setA filteredSetUsingPredicate:predicate];
NSLog(@"Elements > 3: %@", filtered);
}
@end
// MARK: - 3. NSOrderedSet
@interface OrderedSetDemo : NSObject
+ (void)demonstrateOrderedSet {
NSLog(@"\n--- Ordered Set ---");
// Create ordered set
NSOrderedSet *ordered = [NSOrderedSet orderedSetWithObjects:
@"First", @"Second", @"Third", @"First", nil];
NSLog(@"Ordered set: %@", ordered);
NSLog(@"Count: %lu", (unsigned long)ordered.count);
// Access by index
NSString *first = [ordered objectAtIndex:0];
NSString *last = [ordered lastObject];
NSString *second = [ordered objectAtIndex:1];
NSLog(@"First: %@", first);
NSLog(@"Second: %@", second);
NSLog(@"Last: %@", last);
// Index of object
NSUInteger index = [ordered indexOfObject:@"Third"];
NSLog(@"Index of 'Third': %lu", (unsigned long)index);
// Contains
BOOL contains = [ordered containsObject:@"Second"];
NSLog(@"Contains 'Second': %@", contains ? @"YES" : @"NO");
// Mutable ordered set
NSMutableOrderedSet *mutable = [ordered mutableCopy];
[mutable insertObject:@"New" atIndex:1];
NSLog(@"After insert at 1: %@", mutable);
[mutable removeObjectAtIndex:0];
NSLog(@"After remove at 0: %@", mutable);
[mutable exchangeObjectAtIndex:0 withObjectAtIndex:1];
NSLog(@"After swap 0 and 1: %@", mutable);
// Reverse
NSArray *reversedArray = [[mutable reverseObjectEnumerator] allObjects];
NSOrderedSet *reversed = [NSOrderedSet orderedSetWithArray:reversedArray];
NSLog(@"Reversed: %@", reversed);
}
@end
// MARK: - 4. Counted Set
@interface CountedSetDemo : NSObject
+ (void)demonstrateCountedSet {
NSLog(@"\n--- Counted Set ---");
NSCountedSet *bag = [NSCountedSet set];
// Add objects (can have duplicates)
[bag addObject:@"Apple"];
[bag addObject:@"Banana"];
[bag addObject:@"Apple"];
[bag addObject:@"Cherry"];
[bag addObject:@"Apple"];
[bag addObject:@"Banana"];
NSLog(@"Bag (counted set):");
for (NSString *fruit in bag) {
NSInteger count = [bag countForObject:fruit];
NSLog(@" %@ x %ld", fruit, (long)count);
}
// Unique objects
NSLog(@"Unique objects: %lu", (unsigned long)bag.count);
// Remove one
[bag removeObject:@"Apple"];
NSLog(@"\nAfter removing one Apple:");
for (NSString *fruit in bag) {
NSInteger count = [bag countForObject:fruit];
NSLog(@" %@ x %ld", fruit, (long)count);
}
}
@end
// MARK: - 5. Set Use Cases
@interface SetUseCases : NSObject
+ (void)removeDuplicates:(NSArray *)array {
NSLog(@"\n--- Remove Duplicates ---");
NSLog(@"Original array: %@", array);
NSSet *uniqueSet = [NSSet setWithArray:array];
NSArray *uniqueArray = [uniqueSet allObjects];
NSLog(@"Unique elements: %@", uniqueArray);
}
+ (void)findCommonElements:(NSArray *)array1 array2:(NSArray *)array2 {
NSLog(@"\n--- Find Common Elements ---");
NSSet *set1 = [NSSet setWithArray:array1];
NSSet *set2 = [NSSet setWithArray:array2];
NSMutableSet *intersection = [set1 mutableCopy];
[intersection intersectSet:set2];
NSLog(@"Array 1: %@", array1);
NSLog(@"Array 2: %@", array2);
NSLog(@"Common: %@", [intersection allObjects]);
}
+ (void)demonstrateUseCases {
NSLog(@"\n--- Set Use Cases ---");
// Remove duplicates
NSArray *duplicates = @[@"A", @"B", @"A", @"C", @"B", @"D", @"A"];
[self removeDuplicates:duplicates];
// Find common
NSArray *list1 = @[@(1), @(2), @(3), @(4), @(5)];
NSArray *list2 = @[@(3), @(4), @(5), @(6), @(7)];
[self findCommonElements:list1 array2:list2];
// Tags example
NSMutableSet *userTags = [NSMutableSet setWithObjects:@"ios", @"swift", @"objective-c", nil];
NSLog(@"\n--- Tag Management ---");
NSLog(@"User tags: %@", userTags);
// Add tag (won't duplicate)
[userTags addObject:@"swift"];
NSLog(@"After adding 'swift' again: %@", userTags);
// Remove tag
[userTags removeObject:@"objective-c"];
NSLog(@"After removing 'objective-c': %@", userTags);
// Check user has tag
BOOL hasIos = [userTags containsObject:@"ios"];
BOOL hasAndroid = [userTags containsObject:@"android"];
NSLog(@"Has 'ios': %@", hasIos ? @"YES" : @"NO");
NSLog(@"Has 'android': %@", hasAndroid ? @"YES" : @"NO");
// Related tags
NSSet *relatedTags = [NSSet setWithObjects:@"macos", @"xcode", @"cocoa", nil];
NSMutableSet *suggested = [userTags mutableCopy];
[suggested unionSet:relatedTags];
NSLog(@"Suggested tags: %@", suggested);
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Sets Examples ===\n");
// 1. Immutable
[SetBasics demonstrateImmutableSet];
// 2. Mutable
[SetBasics demonstrateMutableSet];
// 3. Operations
[SetOperations demonstrateOperations];
// 4. Ordered set
[OrderedSetDemo demonstrateOrderedSet];
// 5. Counted set
[CountedSetDemo demonstrateCountedSet];
// 6. Use cases
[SetUseCases demonstrateUseCases];
NSLog(@"\n=== Sets Examples Completed ===");
}
return 0;
}
💻 Пользовательские Структуры Данных objectivec
🟡 intermediate
⭐⭐⭐⭐
Реализовать пользовательские классы, связанные списки, стеки, очереди и деревья
⏱️ 35 min
🏷️ objectivec, macos, data structures, custom
Prerequisites:
Intermediate Objective-C, Data structures knowledge
// macOS Objective-C Custom Data Structures Examples
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Linked List
@class ListNode;
@interface ListNode : NSObject
@property (nonatomic, strong) id value;
@property (nonatomic, strong) ListNode *next;
+ (instancetype)nodeWithValue:(id)value;
@end
@implementation ListNode
+ (instancetype)nodeWithValue:(id)value {
ListNode *node = [[ListNode alloc] init];
node.value = value;
node.next = nil;
return node;
}
- (NSString *)description {
return [NSString stringWithFormat:@"%@", self.value];
}
@end
@interface LinkedList : NSObject
@property (nonatomic, strong) ListNode *head;
@property (nonatomic, assign) NSUInteger count;
- (void)append:(id)value;
- (void)prepend:(id)value;
- (void)removeValue:(id)value;
- (BOOL)contains:(id)value;
- (NSArray *)toArray;
- (void)print;
@end
@implementation LinkedList
- (instancetype)init {
self = [super init];
if (self) {
_head = nil;
_count = 0;
}
return self;
}
- (void)append:(id)value {
ListNode *newNode = [ListNode nodeWithValue:value];
if (!self.head) {
self.head = newNode;
} else {
ListNode *current = self.head;
while (current.next) {
current = current.next;
}
current.next = newNode;
}
self.count++;
}
- (void)prepend:(id)value {
ListNode *newNode = [ListNode nodeWithValue:value];
newNode.next = self.head;
self.head = newNode;
self.count++;
}
- (void)removeValue:(id)value {
if (!self.head) return;
// Remove head if matches
if ([self.head.value isEqual:value]) {
self.head = self.head.next;
self.count--;
return;
}
ListNode *current = self.head;
while (current.next) {
if ([current.next.value isEqual:value]) {
current.next = current.next.next;
self.count--;
return;
}
current = current.next;
}
}
- (BOOL)contains:(id)value {
ListNode *current = self.head;
while (current) {
if ([current.value isEqual:value]) {
return YES;
}
current = current.next;
}
return NO;
}
- (NSArray *)toArray {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count];
ListNode *current = self.head;
while (current) {
[array addObject:current.value];
current = current.next;
}
return [array copy];
}
- (void)print {
NSLog(@"LinkedList (%lu elements):", (unsigned long)self.count);
ListNode *current = self.head;
NSMutableString *result = [NSMutableString string];
while (current) {
[result appendFormat:@"%@", current.value];
if (current.next) {
[result appendString:@" -> "];
}
current = current.next;
}
NSLog(@"%@", result);
}
@end
// MARK: - 2. Stack
@interface Stack : NSObject
@property (nonatomic, strong) NSMutableArray *storage;
- (void)push:(id)object;
- (id)pop;
- (id)peek;
- (BOOL)isEmpty;
- (NSUInteger)count;
@end
@implementation Stack
- (instancetype)init {
self = [super init];
if (self) {
_storage = [NSMutableArray array];
}
return self;
}
- (void)push:(id)object {
[self.storage addObject:object];
}
- (id)pop {
if (self.storage.count == 0) {
return nil;
}
id obj = [self.storage lastObject];
[self.storage removeLastObject];
return obj;
}
- (id)peek {
return [self.storage lastObject];
}
- (BOOL)isEmpty {
return self.storage.count == 0;
}
- (NSUInteger)count {
return self.storage.count;
}
@end
@interface StackDemo : NSObject
+ (BOOL)checkParentheses:(NSString *)string {
Stack *stack = [[Stack alloc] init];
NSDictionary *pairs = @{
@")": @"(",
@"}": @"{",
@"]": @"["
};
for (NSInteger i = 0; i < string.length; i++) {
unichar c = [string characterAtIndex:i];
NSString *charStr = [NSString stringWithCharacters:&c length:1];
if ([charStr isEqualToString:@"("] ||
[charStr isEqualToString:@"{"] ||
[charStr isEqualToString:@"["]) {
[stack push:charStr];
} else if ([charStr isEqualToString:@")"] ||
[charStr isEqualToString:@"}"] ||
[charStr isEqualToString:@"]"]) {
if ([stack isEmpty]) {
return NO;
}
NSString *top = [stack peek];
NSString *expected = pairs[charStr];
if (![top isEqualToString:expected]) {
return NO;
}
[stack pop];
}
}
return [stack isEmpty];
}
+ (void)demonstrateStack {
NSLog(@"--- Stack ---");
Stack *stack = [[Stack alloc] init];
// Push
[stack push:@"First"];
[stack push:@"Second"];
[stack push:@"Third"];
NSLog(@"Count: %lu", (unsigned long)[stack count]);
NSLog(@"Peek: %@", [stack peek]);
// Pop
while (![stack isEmpty]) {
NSLog(@"Pop: %@", [stack pop]);
}
// Parentheses check
NSLog(@"\nParentheses check:");
NSArray *tests = @[@"(a + b)", @"{[()]}", @"(]", @"((())"];
for (NSString *test in tests) {
BOOL valid = [self checkParentheses:test];
NSLog(@"%@: %@", test, valid ? @"Valid" : @"Invalid");
}
}
@end
// MARK: - 3. Queue
@interface Queue : NSObject
@property (nonatomic, strong) NSMutableArray *storage;
- (void)enqueue:(id)object;
- (id)dequeue;
- (id)peek;
- (BOOL)isEmpty;
- (NSUInteger)count;
@end
@implementation Queue
- (instancetype)init {
self = [super init];
if (self) {
_storage = [NSMutableArray array];
}
return self;
}
- (void)enqueue:(id)object {
[self.storage addObject:object];
}
- (id)dequeue {
if (self.storage.count == 0) {
return nil;
}
id obj = self.storage[0];
[self.storage removeObjectAtIndex:0];
return obj;
}
- (id)peek {
if (self.storage.count == 0) {
return nil;
}
return self.storage[0];
}
- (BOOL)isEmpty {
return self.storage.count == 0;
}
- (NSUInteger)count {
return self.storage.count;
}
@end
@interface QueueDemo : NSObject
+ (void)demonstrateQueue {
NSLog(@"\n--- Queue ---");
Queue *queue = [[Queue alloc] init];
// Enqueue
[queue enqueue:@"Task 1"];
[queue enqueue:@"Task 2"];
[queue enqueue:@"Task 3"];
NSLog(@"Count: %lu", (unsigned long)[queue count]);
NSLog(@"Peek: %@", [queue peek]);
// Dequeue
while (![queue isEmpty]) {
NSLog(@"Dequeue: %@", [queue dequeue]);
}
// Task queue simulation
NSLog(@"\nTask queue simulation:");
Queue *taskQueue = [[Queue alloc] init];
[taskQueue enqueue:@"Download file"];
[taskQueue enqueue:@"Process data"];
[taskQueue enqueue:@"Save to disk"];
while (![taskQueue isEmpty]) {
NSString *task = [taskQueue dequeue];
NSLog(@"Processing: %@", task);
// Simulate processing
[NSThread sleepForTimeInterval:0.2];
}
}
@end
// MARK: - 4. Binary Tree
@class TreeNode;
@interface TreeNode : NSObject
@property (nonatomic, strong) id value;
@property (nonatomic, strong) TreeNode *left;
@property (nonatomic, strong) TreeNode *right;
+ (instancetype)nodeWithValue:(id)value;
- (void)inOrderTraversal:(void (^)(id))visitor;
@end
@implementation TreeNode
+ (instancetype)nodeWithValue:(id)value {
TreeNode *node = [[TreeNode alloc] init];
node.value = value;
node.left = nil;
node.right = nil;
return node;
}
- (void)inOrderTraversal:(void (^)(id))visitor {
if (self.left) {
[self.left inOrderTraversal:visitor];
}
if (visitor) {
visitor(self.value);
}
if (self.right) {
[self.right inOrderTraversal:visitor];
}
}
@end
@interface BinarySearchTree : NSObject
@property (nonatomic, strong) TreeNode *root;
- (void)insert:(id)value;
- (BOOL)contains:(id)value;
- (NSArray *)inOrderTraversal;
@end
@implementation BinarySearchTree
- (instancetype)init {
self = [super init];
if (self) {
_root = nil;
}
return self;
}
- (void)insert:(NSNumber *)value {
TreeNode *newNode = [TreeNode nodeWithValue:value];
if (!self.root) {
self.root = newNode;
return;
}
TreeNode *current = self.root;
while (YES) {
if ([value compare:current.value] == NSOrderedAscending) {
if (!current.left) {
current.left = newNode;
break;
}
current = current.left;
} else {
if (!current.right) {
current.right = newNode;
break;
}
current = current.right;
}
}
}
- (BOOL)contains:(NSNumber *)value {
TreeNode *current = self.root;
while (current) {
NSComparisonResult result = [value compare:current.value];
if (result == NSOrderedSame) {
return YES;
} else if (result == NSOrderedAscending) {
current = current.left;
} else {
current = current.right;
}
}
return NO;
}
- (NSArray *)inOrderTraversal {
NSMutableArray *result = [NSMutableArray array];
if (self.root) {
[self.root inOrderTraversal:^(id value) {
[result addObject:value];
}];
}
return [result copy];
}
@end
@interface TreeDemo : NSObject
+ (void)demonstrateTree {
NSLog(@"\n--- Binary Search Tree ---");
BinarySearchTree *bst = [[BinarySearchTree alloc] init];
// Insert values
NSArray *values = @[@(50), @(30), @(70), @(20), @(40), @(60), @(80)];
for (NSNumber *value in values) {
[bst insert:value];
}
// Traversal
NSArray *sorted = [bst inOrderTraversal];
NSLog(@"In-order traversal: %@", sorted);
// Search
NSNumber *target = @(40);
BOOL found = [bst contains:target];
NSLog(@"Contains %@: %@", target, found ? @"YES" : @"NO");
target = @(45);
found = [bst contains:target];
NSLog(@"Contains %@: %@", target, found ? @"YES" : @"NO");
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Custom Data Structures Examples ===\n");
// 1. Linked list
NSLog(@"--- Linked List ---");
LinkedList *list = [[LinkedList alloc] init];
[list append:@"First"];
[list append:@"Second"];
[list append:@"Third"];
[list prepend:@"Zero"];
[list print];
NSLog(@"Contains 'Second': %@", [list contains:@"Second"] ? @"YES" : @"NO");
[list removeValue:@"Second"];
[list print];
NSLog(@"As array: %@", [list toArray]);
// 2. Stack
[StackDemo demonstrateStack];
// 3. Queue
[QueueDemo demonstrateQueue];
// 4. Tree
[TreeDemo demonstrateTree];
NSLog(@"\n=== Custom Data Structures Examples Completed ===");
}
return 0;
}