تدارک ساختار ابتدایی این مطلب
در اینجا اینترفیسی را که بیانگر ساختار شیء شخص است، به صورت ذیل ایجاد میکنیم:
export interface Person { name: string; age: number; }
export class LinqTestsComponent { people: Person[] = [ { name: "User 4", age: 27 }, { name: "User 5", age: 42 }, { name: "User 6", age: 8 }, { name: "User 1", age: 20 }, { name: "User 2", age: 35 }, { name: "User 3", age: 78 } ]; }
همچنین سه متد ذیل را نیز برای لاگ کردن عنوان آزمایش، نمایش محتوای آرایهی اصلی و نمایش نتیجهی آزمایش، به این کلاس اضافه میکنیم:
logTitle(title: string) { console.log(`%c${title}`, "background: #222; color: #bada55"); } logOriginalArray() { console.log(`original this.people:${JSON.stringify(this.people)}`); } logResult(message: string, result: any) { console.log(`${message}:${JSON.stringify(result)}`); }
معادل متد Where در TypeScript
متد filter که جزو متدهای توکار ES5 است، میتواند معادلی برای متد Where، جهت فیلتر کردن عناصر بر اساس یک خاصیت، یا چندین خاصیت باشد:
equivalentToWhere() { const youngerThan40 = this.people.filter(person => person.age < 40); // ECMAScript 5 this.logResult("People younger than 40", youngerThan40); // Filtering on Multiple Criteria const youngsters = this.people.filter( person => person.age < 40 && person.name.toLocaleLowerCase().indexOf("user") !== -1); this.logResult("Users younger than 40", youngsters); }
People younger than 40:[ {"name":"User 4","age":27}, {"name":"User 6","age":8}, {"name":"User 1","age":20}, {"name":"User 2","age":35} ] Users younger than 40:[ {"name":"User 4","age":27}, {"name":"User 6","age":8}, {"name":"User 1","age":20}, {"name":"User 2","age":35} ]
معادل متد Any در TypeScript
متد some که جزو متدهای توکار ES5 است، میتواند معادلی برای متد Any باشد. اگر یکی از عناصر آرایه، بر اساس شرط تعیین شده یافت شود، این متد مقدار true را باز میگرداند:
equivalentToAny() { const anyUnder40 = this.people.some(person => person.age < 40); // ECMAScript 5 this.logResult("Are any people under 40?", anyUnder40); // true // Filtering on Criteria Matching any Object Properties const filterBy = "user"; const anyUsers = this.people.filter(person => Object.keys(person).some(property => { let value = (<any>person)[property]; if (typeof value === "string") { value = value.toLocaleLowerCase(); } return value.toString().indexOf(filterBy) !== -1; }) ); this.logResult("anyUsers", anyUsers); }
Are any people under 40?:true anyUsers:[ {"name":"User 4","age":27}, {"name":"User 5","age":42}, {"name":"User 6","age":8}, {"name":"User 1","age":20}, {"name":"User 2","age":35}, {"name":"User 3","age":78} ]
در مثال دوم، جستجویی بر روی تمام خواص شیء شخص انجام شدهاست. در اینجا توسط متد Object.keys، لیست خواص شیء یافت شدهاست. سپس بر روی این لیست توسط متد some، بررسی شدهاست که آیا خاصیت رشتهای وجود دارد که مساوی عبارت filterBy باشد؟ حاصل این بررسی به عنوان شرط متد filter جهت بازگشت آرایهی متناظری از اشخاص یافت شده، استفاده شدهاست.
معادل متد Contains در TypeScript
متد includes که جزو متدهای توکار ES7 است، میتواند معادلی برای متد Contains باشد و کار آن بررسی وجود عنصری در یک لیست است:
equivalentToContains() { const searchElement: Person = { name: "User 4", age: 27 }; const containsUser4 = this.people.includes(searchElement); // ECMAScript 2016 = ECMAScript 7 this.logResult("Contains searchElement", containsUser4); // false -> only compares by reference and not by value. const indexOfUser4 = this.people.indexOf(searchElement); // ECMAScript 5 this.logResult("indexOfUser4", indexOfUser4); // -1 -> only compares by reference and not by value. const stringifiedObj = JSON.stringify(searchElement); const includesUser4 = this.people.some(person => JSON.stringify(person) === stringifiedObj); this.logResult("includesUser4", includesUser4); // true -> compares by by value. }
یکی از روشهای مقایسهی بر اساس تمام مقادیر خواص یک شیء، استفاده از متد JSON.stringify است که اگر آنرا با متد some ترکیب کنیم، میتوان به نتیجهی مطلوبی رسید:
Contains searchElement:false indexOfUser4:-1 includesUser4:true
معادل متد All در TypeScript
متد every که جزو متدهای توکار ES5 است، میتواند معادلی برای متد All باشد و کار آن بررسی صحت شرط اعمالی، بر روی تک تک عناصر لیست است. اگر این بررسی با موفقیت صورت گرفت، مقدار true را بازگشت میدهد:
equivalentToAll() { const allUnder30 = this.people.every(person => person.age < 30); // ECMAScript 5 this.logResult("Are all people under 30?", allUnder30); // false }
Are all people under 30?:false
معادل متدهای First و FirstOrDefault در TypeScript
میتوان از متدهای filter و یا find بومی ES5 و ES 6 برای شبیه سازی متدهای First (یافتن اولین عنصر درخواستی در یک لیست) و FirstOrDefault استفاده کرد:
equivalentToFirstOrDefault() { const vahidOrDefault = this.people.filter(item => item.name === "Vahid")[0] || null; // ECMAScript 5 this.logResult("vahidOrDefault", vahidOrDefault); const user1OrDefault = this.people.find(item => item.name === "User 1") || null; // ECMAScript 2015 = ECMAScript 6 this.logResult("user1OrDefault", user1OrDefault); }
معادل متد FindIndex در TypeScript
متد findIndex که جزو متدهای توکار ES6 است، میتواند معادلی برای متد FindIndex در جهت یافتن ایندکس عنصری در یک لیست، بر اساس شرط درخواستی، باشد.
equivalentToFindIndex() { const index = this.people.findIndex(person => person.age === 8); // ECMAScript 2015 = ECMAScript 6 this.logResult("index of the user with age 8", index) }
index of the user with age 8:2
معادل متد Select در TypeScript
متد map که جزو متدهای توکار ES5 است، میتواند معادلی برای متد Select، برای تغییر شکل نهایی خروجی یک لیست باشد:
equivalentToSelect() { const names = this.people.map(person => person.name); // ECMAScript 5 this.logResult("Selected the names of people", names); }
Selected the names of people:["User 4","User 5","User 6","User 1","User 2","User 3"]
معادل متد Aggregate در TypeScript
متد reduce که جزو متدهای توکار ES5 است، میتواند شبیه به متد Aggregate عمل کند و لیستی از عناصر را به یک مقدار کاهش دهد:
equivalentToAggregate() { // ECMAScript 5 const aggregate = this.people.reduce((person1, person2) => { return { name: "", age: person1.age + person2.age }; }); this.logResult("Aggregate age", aggregate.age); // { age: 210 } }
Aggregate age:210
معادل متد ForEach در TypeScript
متد forEach که جزو متدهای توکار ES5 است، میتواند معادلی برای متد ForEach باشد که روشی functional برای پیمودن عناصر یک لیست است:
equivalentToForEach() { // ECMAScript 5 this.people.forEach(person => { this.logResult("person", person); }); }
person:{"name":"User 4","age":27} person:{"name":"User 5","age":42} person:{"name":"User 6","age":8} person:{"name":"User 1","age":20} person:{"name":"User 2","age":35} person:{"name":"User 3","age":78}
معادل متد OrderBy در TypeScript
متد sort که جزو متدهای توکار ES5 است، میتواند معادلی برای متد OrderBy باشد که جهت مرتب سازی عناصر یک لیست از آن استفاده میشود:
// ECMAScript 5 let orderedByAgeAscending = this.people.sort((person1, person2) => { const a = person1.age; const b = person2.age; return a > b ? 1 : -1; }); this.logResult("Ordered by age ascending", orderedByAgeAscending);
- مساوی صفر باشد، تغییری را به وجود نمیآورد.
- کمتر از صفر باشد، اولین عنصر را قبل از دومین عنصر قرار میدهد.
- بیشتر از صفر باشد، دومین عنصر را پس از اولین عنصر قرار میدهد.
منطق مقایسهی فوق را به صورت ذیل نیز میتوان خلاصه کرد:
orderedByAgeAscending = this.people.sort((person1, person2) => person1.age - person2.age); this.logResult("Ordered by age ascending", orderedByAgeAscending);
Ordered by age ascending:[ {"name":"User 6","age":8}, {"name":"User 1","age":20}, {"name":"User 4","age":27}, {"name":"User 2","age":35}, {"name":"User 5","age":42}, {"name":"User 3","age":78} ]
const orderedByName = this.people.sort((person1, person2) => { // name1.localeCompare(name2) // is case insensitive // or use toUpperCase() to ignore character casing const name1 = person1.name.toUpperCase(); const name2 = person2.name.toUpperCase(); return name1 > name2 ? 1 : -1; }) this.logResult("Ordered by name", orderedByName); this.logOriginalArray();
Ordered by name:[ {"name":"User 1","age":20}, {"name":"User 2","age":35}, {"name":"User 3","age":78}, {"name":"User 4","age":27}, {"name":"User 5","age":42}, {"name":"User 6","age":8} ] original this.people:[ {"name":"User 1","age":20}, {"name":"User 2","age":35}, {"name":"User 3","age":78}, {"name":"User 4","age":27}, {"name":"User 5","age":42}, {"name":"User 6","age":8} ]
امکان ترکیب زنجیروار متدهای کار بر روی لیستها در TypeScript
همانند LINQ، در اینجا نیز میتوان متدهای فوق را به صورت زنجیروار بر روی یک لیست فراخوانی و اجرا کرد:
chainFunctionCalls() { const namesOfPeopleOver30OrderedDesc = this.people .filter(person => person.age > 30) .map(person => person.name) .sort((name1, name2) => { // name1.localeCompare(name2) // is case insensitive // or use toUpperCase() to ignore character casing name1 = name1.toUpperCase(); name2 = name2.toUpperCase(); return name2 > name1 ? 1 : -1; }); this.logResult("the names of all people over 30 ordered by name descending", namesOfPeopleOver30OrderedDesc); }
the names of all people over 30 ordered by name descending:["User 5","User 3","User 2"]
معادل متد Skip در TypeScript
متد splice که جزو متدهای توکار ES5 است، میتواند شبیه به متد Skip عمل کند. این متد آرایهای را بازگشت میدهد که حاوی عناصری است که پس از تعداد ذکر شده، در آرایهی اصلی وجود دارند:
equivalentToSkip() { const skip2 = this.people.splice(2); // ECMAScript 5 this.logResult("skip2 -> the deleted elements", skip2); this.logOriginalArray(); }
skip2 -> the deleted elements:[ {"name":"User 3","age":78}, {"name":"User 4","age":27}, {"name":"User 5","age":42}, {"name":"User 6","age":8} ] original this.people:[ {"name":"User 1","age":20}, {"name":"User 2","age":35} ]