9. LINQ Operators || C# 10 Flashcards

1
Q

What are the standart query operators categories?

Give an example of each

A
  1. Sequence in, sequence out (sequence -> sequence)
    Where<>, OrderBy<>, ToList<> and others..
  2. Sequence in, single element or scalar value out
    First<>, Count, Contains<>
  3. Nothing in, sequence out (generation methods)
    Empty, Range, Repeat
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Explain:

Where<> clause

A

Where returns the elements from the input sequence that satisfy the given predicate:
IEnumerable<string> query = names.Where(name => name.EndsWith("y"));
A Where<> clause can appear more than once in a query and be interspersed with let, orderby and join clauses.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What would be equivalent to SQL’s LIKE '%abc%'? What other SQL command this method could substitute?

A

c.Name.Contains(“abc”). It can also act like IN operator in SQL - checking if element is in the table.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Explain the difference between:

Take() and Skip() clauses

A

Take() emits the first n elements and discards the rest;
Skip() discards the first n elements and emits the rest. So its opposite.
~~~
IQueryable<Book> query = dbContext.Books
.Where(b => b.Title.Contains("mercury"))
.OrderBy(b => b.Title).Skip(20).Take(20);
~~~</Book>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Explain the difference between:

  • Take(5..) and Skip(5)
  • Take(..^5) and SkipLast(5);
A

The meaning are equal in each row.
* Take(5..) == Skip(5)
* Take(..^5) == SkipLast(5)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Explain the difference between:

Distinct() and DistinctBy<>

A

Distinct() will return distinct elements in the given sequence;
DistinctBy<> will also return disctinct elements in a sequence but before apply the given logical operations. The returned results will be after the additional operation application such as:
new[] {1.0, 1.1, 2.0, 2.1, 3.0, 3.1}.DistincBy(n => Math.Round(n, 0));
The first step will be to apply the logical operation, after which the sequence will look like this:
new[] {1, 1, 2, 2, 3, 3}. Then the Distinct() method will take place and return only the distinct elements in the sequence. The result will be: 1, 2, 3

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Define:

Select<> clause

A

With Select you always get the same number of elements that you started with. Each elements however, can be transformed in any manner by the mabda function:
IEnumerable<string> query = FontFamily.Families.Select(s => s.Name);
It does also accept second parameter in lambda expression to enable indexed projection:
IEnumerable<string> query = names.Select((s, i) => i + "=" + s); // {“0=Tom”, “1=Harry”…}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Explain:

Correlated subquery

A

A subquery is correlated if it references an object in the outer query. In the example below it references ‘d’, the directory beingenumerated:
~~~
string tempPath = Path.GetPath();
DirectoryInfo[] dirs = new DirectoryInfo(tempPath).GetDirectories();

var query = from d in dirs
where (d.Attributes & FileAttributes.System) == 0
select new
{
DirectoryName = d.FullName,
Created = d.CreationTime,
Files = from f in d.GetFiles()
where (f.Attributes & FileAttributes.Hidden) == 0
select new {FileName = f.Name, f.Lenth, }

};
~~~

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Explain the difference between:

Select and SelectMany

A

Lets say we have a array of people names:
string[] names = ["Harry Styles", "Lewis Capaldi", "Beyonce Knowles"]; and we would like to turn this into the array of names where first and last name is two separate items in array.
If we would use select we would take each element, use Split(), which would return array of elements. We would make array of arrays and then make a double foreach loop to loop through and make something of that:
~~~
IEnumerable<string[]> splittedNames = names.Select(s => s.Split());
foreach(string[] stringArray in splittedNames){
foreach(string stringElement in stringArray){
…..
}
}
~~~
Now with SelectMany we could do the same with a single line:
~~~
IEnumerable<string> query = names.SelectMany(s => s.Split());
foreach(string name in query){
.....
}
~~~
With `SelectMany` we can expand child sequences, flatten nested collections, and join two collections into a flat output sequence. If we would translate to query syntax `SelectMany` would have two range variables (from n in names...)</string>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What is the SelectMany equivalent in SQL?

A

SelectMany can perform cross-joins, non-equi joins, inner joins and left outer joins

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How to include data from child table vs parent table in LINQ?

A

Child : each from clause introduces a new child table.
Parent : to include data from a parent table you simply navigate to the property:

from c in dbContext.Customers
select new { Name = c.Name, SalesPerson = c.SalesPerson.Name};

SalesPerson.Name is a parent property here

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is Select() equivalent to in SQL?

A

Select() subquery yields a result analogous to a left outer join: every outer element is included, regardless of whether it has any of other parameters

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

How we can turn left outer join to the inner join but written in LINQ?

A

We should replace Select() (left outer join) with SelectMany(): in the process of flattening the query we will switch to an inner join: customers are included only for whom one or more high-value purchases exist:

from c in dbContext.Customers
from p in c.Purchaces
where p.Price > 1000
select new { c.Name, p.Description, p.Price };
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What is SQL equivalent of Join()? How does this method work?

A

INNER JOIN
Applies a lookup strategy to match elements from two collections, emitting a flat result set

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

We can use both SelectMany() and Join() to inner join the elements with matching keys. Which is better over other?

A

Although both queries yield the same results, the Join() query is considerably faster because its implementation in Enumerable preloads the inner collection (purchase) into a keyed lookup

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Let’s say we have this block of code:
~~~
from c in customers
select new
{
CustName = c.Name,
custPurchases = purchases.Where(w => c.ID == w.CustomerId)
};
~~~
What would be a more efficient way of writting the same thing?

A

More efficient way would be to use GroupJoin like this:
~~~
from c in customers
join p in purchases ob c.ID equals p.CustomerID
into customerPurchases
select new {CustNames = c.Name, custPurchases };
~~~
By doing this the left outer join is performed by default. This means that if the customer does not have a purchase - it wont be excluded. To do that we need to do an inner join

17
Q

Explain

“lookup” in LINQ queries?

A

A “lookup” is a sequence of groupings that can be accessed directly by key. Another way to think of it is as a dictionary of sequences - a dictionary that can accept many elements under eah key (sometimes called a multidictionary)
~~~
public interface ILookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement», IEnumerable
{
int Count {get; set;}
bool Contains {get; set;}
IEnumerable<TElement> this [TKey key] {get; }
}
~~~</TElement>

18
Q

Explain what it is and how it works:

Zip operator

A

IEnumerable<TFirst>, IEnumerable<TSecond>=> IEnumerable<TResult>
The Zip operator enumerates two sequences in step, returning a sequence based on applying a function over each element pair :
~~~
int[] numbers = {3, 5, 7};
string[] words = {“three”, “five”, “seven”, “ignored”};
IEnumerable<string> zip = numbers.Zip(words, (n, w) => n + "=" + w);
~~~
zip == "3=three", "5=five", 7="seven"</string>

19
Q

What is the difference between Concat and Union operators?

A

Concat returns all the elements of the first sequence, followed by all the elements of the second.
Union does the same but removes any duplicates

20
Q

What is the difference between Intersect and Except operators?

A

Intersect returns the elements that two sequences have in common.
Except returns the elements in the first input sequence that are not present in the second

21
Q

Explain how OfType is different from Cast operator

A

OfType and Cast accept non-generic IEnumerable collection and emit a generic IEnumerable<T> sequence that you can subsequently query.
Cast and OfType differ in their behaviour when encountering an input element that’s of an incompatible type. Cast throws an exception; OfType ignores the incompatible element.</T>

22
Q

What is the difference between FirstOrDefault and SingleOrDefault operators if they both return just one element?

A

First and FirstOrDefault returns the first element in the sequence, optionally satisfying a predicate;
Single and SingleOrDefault are equivalent to First / FirstOrDefault , but throws and exception if there is more than one match

23
Q

What would be returned by these methods?

int[] numbers = { 1, 2, 3, 4, 5 };
1) numbers.FirstOrDefault(f => f % 2 == 0);
2) numbers.SingleOrDefault(f => f % 2 == 0);

A

FirstOrDefault will return ‘2’ as result;
SingleOrDefault will throw an exception because there are more than one element that fits the expression. To prevent the exception, Single requires exactly one matching element; SingleOrDefault requires one or zero matching elements;

24
Q

Where Single operator is used if First can do the same thing?

A

In EF Core, Single is often used to retrieve a row from a table by primary key (since there can’t be multiple results here);

25
Q

What are the differences between Max and MaxBy (Min / MinBy) operators?

A

MinBy and MaxBy operators return the elements with the smallest or largest value, as determined by a keySelector. Min / Max operators return the smallest or biggest value itself:
~~~
string[] names = {“Tom”, “Richard”, “Harry”, “Marry”, “Jay”};
names.MinBy(m => m.Length);
names.Min(min => min.Length);
~~~
MinBy result : Tom
Min result : 3

26
Q

When a selector expression in manadatory in Aggregation methods like Min, Max, etc.?

A

A selector expression is mandatory if the items themselves are not intrisically comparable - in other words, if they do not implement IComparable<T>:
~~~
Purchase runtimeError = dbContext.Purchase.Min();
decimal? lowestPrice = dbContext.Purchase.Min(m => m.Price);
~~~

27
Q

What does it mean for Agregate method to be seeded or unseeded?

A

Agregate method can be supplied with 3 parameters:
1. First parameter is the seed, from which the accumulation starts.
2. Second argument is an expression to update the accumulated value, given a fresh element..
3. Third argument can be given to project the final result value from the accumulated value;
~~~
int[] numbers = {1, 2, 3};
int sum = numbers.Agregate(0, (total, n) => total + n);
~~~
If we omit the seed value when calling Agregate in which case the first element becomes the implicit seed, and aggregation proceeds from the second element. Here’s an unseeded example :
~~~
int[] numbers = {1, 2, 3};
int sum = numbers.Agregate((total, n) => total + n);
~~~
Although both seeded and unseeded examples return the same result “6”, but the calculations are acctually different:
seeded: 0+1+2+3 = 6
unseeded: 1+2+3 = 6

28
Q

What are the main way to use unseeded aggregations. Give example why

A

The unseeded aggregation methods are intended for use with delegates that are commutative and associative. If used otherwise, the result is either unintuitive or nondeterministic. Consider the following function:
(total, n) => total + n * n
This neither commutative nor associative.
~~~
int[] numbers = {1, 2, 3};
int sum = numbers.Aggregate((total, n) => total + n*n);
~~~
Instead of calculating this as
2*2 + 3*3 + 4*4 // 29
It calculates:
2 + 3*3 + 4*4 // 27

29
Q

How does .Range() operator work?

A

Range accepts a starting index and count (both ints):
~~~
foreach (int i in Enumerable.Range(5, 3))
Console.WriteLine(i + “ ”);
``` // 5 6 7

30
Q

How does the .Repeat() operator work?

A

Repeat accepts an element to repeat and the of repetitions:
~~~
foreach (bool x in Enumerable.Repeat(true, 3))
Console.Write(x + “ ”);
``` // true true true