SEtFOrthYOurSEtIDears[C #, LINQ]
WRittenALlenLEE
0. TAbleCOntent
- 1.WHatAReDIfferences?
- 2.USingSEt <T>COllectionPOwerCOllection.
- 3.USingSEtOPeratorsLINQ.
- 4.SEt <T>COllection.SEtOPerators.
- 5.FUrtherCOnsiderations.
- 6.EXercises.
1. WHatAReDIfferences?
One day, my friend Heng asked me what tools I could use to compare two folders and find different files. First, let's look at his requirements:
- 1) You only need to compare the files in the current folder;
- 2) The files with the same name in the two folders are treated as the same files.
Obviously, if you think of these two folders as two sets,
- A = {A | file in the first folder}
- B = {B | file in the second folder}
The file he is looking for will be the result set obtained by performing a series of set operations on the two sets. See:
The red and yellow circles represent the set a and the Set B respectively. The areas 1 and 2 are the set of "different files" we are looking. Using the set representation, this result set can be expressed as ("'" is the complement set symbol, complete set I = A ∪ B ):
R = (A then B) Then (A then B ))'
However, there is a blind spot in this result set, that is, mixing the two regions 1 and 2 without distinction. What if we only need the result set of one of the regions? Or do we need to display the areas 1 and 2 to the two edit boxes of the GUI respectively?
If we want to use a as the benchmark to find the elements that a does not have in B, then the result set (Region 2) will be expressed:
R2 = (A then B) then )'
If we want to use B as the benchmark to find the elements that B does not have in A, then the result set (Region 1) will be expressed:
R1 = (A then B )'
Obviously, this "direction" factor should be considered in the specific encoding.
After so many theories, we should take a look at the practice. First, let's take a look at how set <t> collection is used.
2. USingSEt <T>COllectionPOwerCOllection.
First, we need to get all the files in the specified path. Since Heng only requires all the files in the current folder, so:
// Code #01
Static String [] Getfilenamesfrom ( String Path)
{
If (Path = Null | Path. Length = 0 )
{
Throw NewArgumentexception ("Parameter cannot be null or empty!");
}
If ( ! Directory. exists (PATH ))
{
Throw NewArgumentexception (string. Format ("{0} does not exist!", PATH ));
}
String [] Filenames = System. Io. Directory. getfiles (PATH );
String [] Result = New String [Filenames. Length];
For ( Int I = 0 ; I < Filenames. length; I ++ )
{
Result [I]=System. Io. Path. getfilename (filenames [I]);
}
Return Result;
}
From the Heng requirements, we can see that we only need to consider the file name, so we have filtered out the path.
Additional reading:
How to determine whether a string is a null string? [C #], Allen Lee
Next, we create a and B collections:
// Code #02
Set < String > A = New Set < String > (Getfilenamesfrom (ARGs [ 0 ]);
Set < String > B = New Set < String > (Getfilenamesfrom (ARGs [ 1 ]);
We can obtain the result set as follows:
// Code #03
Set < String > R1 = A. Difference (B );
Set < String > R2 = B. Difference ();
We know that r is the Union set of R1 and R2. If you need R, you do not need to first find R1 and R2 and then merge them, but directly use the set <t> provided:
// Code #04
Set < String > R = A. Explain ricdifference (B );
// Or
Set < String > R = B. Explain ricdifference ();
These two methods are equivalent Based on the set nature.
Now, let's take a look at how set operators in LINQ operates.
3. USingSEtOPeratorsLINQ.
With LINQ, you can directly "query" the file name in the specified path (of course, you must ensure the correctness of the path ):
// Code #05
VaRA = FromA In System. Io. Directory. getfiles (ARGs [ 0 ])
OrderbyA
SelectSystem. Io. Path. getfilename ();
VaRB = FromB In System. Io. Directory. getfiles (ARGs [ 1 ])
OrderbyB
SelectSystem. Io. Path. getfilename (B ); Then, use the response t of standard query operators to obtain the result set:
// Code #06
VaRR1 = A. Random T (B );
VaRR2 = B. Random T ();
Since the set operators operator of LINQ does not provide a function similar to set <t>. Wide ricdifference, If you need R, you can:
// Code #07
VaRR = R1.union (R2 );
In addition, you can wrap system. Io. Directory. getfiles to check the passed path parameters in your method.
4. SEt <T>COllection.SEtOPerators.
Due to the needs of the plot development, they will inevitably have such a scene. Which one do you choose? Such a plot and a problem make people feel like choosing one that will spend the rest of your life with you ~~~
Personally, I like the maturity of set <t> collection, but I cannot forget the directness of set operators with query. Greedy, I naturally want to be able to enjoy the well-rounded family.
Becky, Sales & Marketing Director of Martin Hotel, decided to investigate the recent drop in occupancy rates.
Becky knew that the cost of retaining an old customer was much lower than the cost of developing a new customer. So she decided to check whether the occupancy rate of old customers in the last quarter had changed? How is it changed?
// Code #08
VaRQ = FromC In MERs
WhereC. Level = Customerlevel. VIP
GroupCByC. checkindate. MonthIntoG
Select New {Month=G. Key, count=G. Group. Count ()} ;
Becky found that the occupancy rate of old customers decreased significantly on a monthly basis. Why? Because these old customers are major customers, they will only stay in five-star hotels, while the local five-star hotels except Martin Hotel are the only ones left to death. Becky found that some people often stayed at the door of the hotel recently. She suspected that her opponent had sent someone to pull a visitor at the door of the hotel, she asked someone to investigate the old customers who had not checked in with these people at the door of the hotel. She got a list, the above lists the old customer names who "disappeared" at the door of the hotel but stayed in the opposite hotel.
She adds the list of lost old customers to the total list of existing customers:
// Code #09
// Getlostviplist () returns an ienumerable <t>
VaRL = Getlostviplist ();
VaRG = FromC In MERs
WhereC. Level = Customerlevel. VIP
SelectC. Name;
VaRT = G. Union (L );
// Getviplist () returns a set <t>
Set < Customer > VIP = Getviplist ();
Set < Customer > Total = New Set < T > (T );
Console. writeline (VIP. isto to (total ));
Now, Becky finally knows the reason for the loss of old customers. She decided to sue the opposite hotel for unfair competition.
5. FUrtherCOnsiderations.
We know that,LINQCurrently, it is just a prototype, andPowercollectionRelease already exists. However, you don't have to worry about providing only four set operations for LINQ. Because LINQ supports extension methods, you can expand the set operations as needed:
// Code #10
Namespace Becky. utils
{
Public Static Bool Isvice < T > ( This Ienumerable < T > First, ienumerable < T > Second)
{
//Add some code here
}
}
In addition, because the operation of the Set must involve the determination of elements, we need to have an understanding of the methods of determining these tools. Set <t> collection uses system. collection. Generic. iequalitycomparer <t>, while set operators uses equals and gethashcode. If you put custom objects in the set, you need to consider these issues.
Additional reading:
Object authentication ity and identityInChapter 6: Common Object operations. Jeffrey Richter.Applied Microsoft. NET Framework programming. Microsoft Press 2002
Finally, because this article focuses on the collection operations and the use of tools, other factors that must be considered in actual projects have been omitted as appropriate. For example, when comparing files, the size of files with the same name is also a factor to consider. In this way, you first need to define different files, extract the factors that must be taken into account, then abstract the representation of a file, and finally project the results of the "query) to the abstract.
6. EXercises.
Heng now adds a requirement that the file size should be taken into account. Only when the file name and file size are the same can the file be regarded as the same. So, how do you think the set <t> collection and set operators solutions should be modified to meet new requirements? In addition, if Heng may raise new requirements in a few days, how do you think you should design the changes to meet such requirements more elastically?