LINQ has a very practical selectmany method, which many people can’t use

Time:2020-12-6

In normal development, we often see that some friends or colleagues are full of various for, foreach when writing code. If there is too much code, the readability is very poor, and it is particularly cumbersome. In fact, there are many methods in FCL to help us improve the sense of reading. In reality, many people can’t use or say they don’t know. I’ll talk to you about this.

1: Selectmany

This method is definitely a powerful tool to improve the development speed. There are too many business scenarios that need to use this function. For example, in my actual application scenario, the merchant sets some labels in advance according to the year and customer type, and then let the system run how many labels are there?

1. Define model

For the convenience of demonstration, here is a simplified code. There is only one dictionary. Key indicates the year, and value: refers to multiple groups of labels of the year.

public class EstimateModel
    {
        public int ShopID { get; set; }

        //Key: year
        public Dictionary<string, List<TagCrowdFilterModel>> YearCrowdFilterDict { get; set; }
    }

    public class TagCrowdFilterModel
    {
        /// <summary>
        ///Screening criteria
        /// </summary>
        public string CrowdFiter { get; set; }

        /// <summary>
        ///Number of people obtained
        /// </summary>
        public int TotalCustomerCount { get; set; }
    }

For clarity, I decided to fill in the data again

public static void Main(string[] args)
        {
            var estimateModel = new EstimateModel()
            {
                ShopID = 1,
                YearCrowdFilterDict = new Dictionary<string, List<TagCrowdFilterModel>>()
                {
                    {
                        "17 years", new list < tagcrowdfiltermodel > ()
                               {
                                 new TagCrowdFilterModel(){ CrowdFiter="between 10 and 20" },
                                 new TagCrowdFilterModel(){ CrowdFiter=" a<10  || a>30" },
                               }
                    },
                    {
                        "18 years", new list < tagcrowdfiltermodel > ()
                               {
                                 new TagCrowdFilterModel(){ CrowdFiter="between 100 and 200" },
                                 new TagCrowdFilterModel(){ CrowdFiter=" a<100  || a>300" },
                               }
                    },
                    {
                        "19 years", new list < tagcrowdfiltermodel > ()
                               {
                                 new TagCrowdFilterModel(){ CrowdFiter="between 1000 and 2000" },
                                 new TagCrowdFilterModel(){ CrowdFiter=" a<1000  || a>3000" },
                               }
                    }
                }
            };
        }

        public static int GetCustomerID(string crowdfilter)
        {
            return BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0);
        }

2. Realize the requirements

If the method of getcustomerfilter in turn is very simple, how can you get the number of people in the demand by calling the method of getcustomerfilter? That’s right. A lot of people are probably just two foreach.

        foreach (var year in estimateModel.YearCrowdFilterDict.Keys)
        {
            var yearCrowdFitlerList = estimateModel.YearCrowdFilterDict[year];

            foreach (var crowdFitler in yearCrowdFitlerList)
            {
                crowdFitler.TotalCustomerCount = GetCustomerID(crowdFitler.CrowdFiter);
            }
        }

It seems that the code is very fresh, but in reality, there is no such good thing. The real situation is that there may be a customer type in the year, a commodity on the customer type, and a merchant on the commodity. In such a deep level, you need as many as three foreach, four foreach and even five foreach to complete. And then put a picture for you to see if you have a big head

LINQ has a very practical selectmany method, which many people can't use

3. Optimization method

If you can select many, it only needs a chain writing method. Is it simple and crude? Although the performance is not comparable to the command-based writing method, its readability and viewing ability are really up to several grades.

            estimateModel.YearCrowdFilterDict.SelectMany(m => m.Value).ToList().ForEach(m =>
                m.TotalCustomerCount = GetCustomerID(m.CrowdFiter)
            );

2: Principle Exploration

1. MSDN interpretation

Project each element of the sequence to IEnumerable < T >, merge the result sequence into a sequence, and call the result selector function for each element in the sequence
https://docs.microsoft.com/zh…
With the above case explanation, and then look at the sentence of MSDN, I think you should thoroughly understand how to use selectmany.

2. Check the source code

I understand from the macro level. Next, I’ll use ilspy to check the microcode code and find out how this thing is implemented.

public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (selector == null)
    {
        throw Error.ArgumentNull("selector");
    }
    return SelectManyIterator(source, selector);
}

private static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
{
    foreach (TSource item in source)
    {
        foreach (TResult item2 in selector(item))
        {
            yield return item2;
        }
    }
}

Let’s take a closer look at these two foreach, especially the second one. Isn’t the selector (item) the tag set under the year? Then traverse the collection and return each item. The return value is IEnumerable < tresult >, which benefits from the yield syntax sugar. It is essentially an iteration class encapsulated by the compiler, which achieves a delay and is executed on demand. Later, I will share yield specifically, which is very interesting

Well, that’s all for this article. I hope it can help you.

Recommended Today

CentOS7. Installing JDK in 4

In centos7 Install jdk8 in 4 Installing the JDK using rpm 1. Download address:Click to jump to the download page 2. Select the corresponding version 3. Click download to download jdk-8u161-linux-x64.0 via xftp Upload RPM file to Linux 4. Use the RPM command to install: RPM – IVH jdk-8u161-linux-x64 rpm It is installed in the […]