Вопрос

I'm trying to convert a simple piece of Math to Linq.

I want to bundle together the prime factors for several numbers into one collection. Consider the following integers.

8 = 2 * 2 * 2
12 = 2 * 2 * 3

The smallest number divisible by both 8 & 12 is 24, so I'd like the resultant group to contain

{ 2, 2, 2, 3 }

If I use Concat the result is {2,2,2,2,2,3} - not correct If I use Union the result is {2,3} - not correct

Is there a built in Linq Set Manipulation function which will recognise that it needs to keep the maximum number of occurences of an item (i.e. not add another if there are already enough there to satisfy if & add another if there aren't)

Это было полезно?

Решение

Well, it's not any existing function, as I don't think such exists, but pretty simple code is capable of handling this:

        var listA = new List<int> {2, 2, 2};
        var listB = new List<int> {2, 2, 3};

        var grouppedA = listA.GroupBy(i => i).Select(g => new { key = g.Key, count = g.Count()});
        var grouppedB = listB.GroupBy(i => i).Select(g => new { key = g.Key, count = g.Count()});
        var result = grouppedA
            .Union(grouppedB)
            .GroupBy(g => g.key)
            .SelectMany(g => Enumerable.Repeat(g.Key, g.Max(h => h.count)));

        foreach (int i in result)
        {
            Console.Write(i + " ");
        }
        Console.ReadKey();

Output: 2 2 2 3

Другие советы

using System;
using System.Collections.Generic;

public class Sample {
    public static void Main(String[] args) {
        var n8  = toFactors(8);
        var n12 = toFactors(12);
        var uf = unionFactors(n8, n12);//LCM
        printFactors(uf);
    }
    public static void printFactors(Dictionary<long, int> factors){
        Console.Write("{ ");
        foreach(var factor in factors.Keys){
            for(int i=0;i<factors[factor];++i)
                Console.Write( factor + " ");
        }
        Console.WriteLine("}");
    }
    public static Dictionary<long, int> unionFactors(Dictionary<long, int> af, Dictionary<long, int> bf){
        Dictionary<long, int> uf = new Dictionary<long, int>();
        foreach(var kv in af){
            uf.Add(kv.Key, kv.Value);//copy
        }
        foreach(var kv in bf){
            if(uf.ContainsKey(kv.Key)){
                if(kv.Value > uf[kv.Key])//max
                    uf[kv.Key] = kv.Value;
            } else {
                uf.Add(kv.Key, kv.Value);
            }
        }
        return uf;
    }
    public static Dictionary<long, int> toFactors(long num){
        var factors = new Dictionary<long, int>();
        long n = num, i = 2, sqi = 4;
        while(sqi <= n){
            while(n % i == 0){
                n /= i;
                if(factors.ContainsKey(i)){
                    factors[i] += 1;
                } else {
                    factors.Add(i, 1);
                }
            }
            sqi += 2 * (i++) + 1;
        }
        if(n != 1 && n != num){
            if(factors.ContainsKey(i)){
                factors[i] += 1;
            } else {
                factors.Add(i, 1);
            }
        }
        if(factors.Count == 0)
            factors.Add(num, 1);//prime
        return factors;
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top