C# - 对象的分区列表中的大小分区



我有一个很大的对象列表(我已经定义了自己的类(。我需要将此列表划分为许多不同大小的不同分区。一个分区甚至只能包含一个对象。基本上,我试图基于这些对象之间的相似性数量来聚集此列表。

这是我的代码的一个示例,例如:

    class Bar
    {
        public List<Foo> fooList = new List<Foo>();
        // pseudocode of goal
        List<List<Foo>> partitionedlist = new List<List<Foo>>();
        List<Foo> partition1 = Partition(fooList.SelectMany(item.inputs.intersect(item2.inputs)));
    }
    class Foo
    {
        public List<String> inputs = new List<string>();
    }

需要根据对象在其"输入"列表中具有的匹配项(百分比(进行分区。我也希望也能够限制分区的大小。

我认为没有一种有效的方法可以使用Linq来执行此操作,但是您可以根据每个Foo s循环并根据每个Foo与内容的相似方式创建存储桶桶,并在相似性太低时创建一个新的水桶。我将每个 Foo的平均值与所有 Foo s的平均值一起用作单个 Foo和一个水桶( List<Foo>(之间的相似性,并找到了具有最高相似性的水桶。

假设一个用于计算两个 Foo s之间相似性的函数(我使用的是inputs成员的数量除以inputs的最大计数(,您将它们放入存储桶中:

class Bar {
    public List<Foo> fooList = new List<Foo>();
    public List<List<Foo>> partitionedFoos;
    public void PartitionFoos() {
        partitionedFoos = Foo.PartitionFoos(fooList);
    }
}
class Foo {
    public List<String> inputs = new List<string>();
    public double Similarity(Foo anotherFoo) {
        return inputs.Intersect(anotherFoo.inputs).Count()/(double)(inputs.Count+anotherFoo.inputs.Count);
    }
    public static List<List<Foo>> PartitionFoos(List<Foo> foos) {
        var answers = new List<List<Foo>>();
        answers.Add(new List<Foo>());
        var fooe = foos.GetEnumerator();
        if (fooe.MoveNext()) {
            answers[0].Add(fooe.Current);
            while (fooe.MoveNext()) {
                var curFoo = fooe.Current;
                var max = answers.Select((lf, i) => (AvgSimilarity: lf.Average(f => f.Similarity(curFoo)), i)).MaxBy(si => si.AvgSimilarity);
                if (max.AvgSimilarity < 0.4) // time for a new bucket!
                    answers.Add(new List<Foo> { curFoo });
                else
                    answers[max.i].Add(curFoo);
            }
        }
        return answers;
    }
}

ps我使用了我定义的扩展方法来查找最大值:

public static T MaxBy<T, TKey>(this IEnumerable<T> src, Func<T, TKey> key, Comparer<TKey> keyComparer) => src.Aggregate((a, b) => keyComparer.Compare(key(a), key(b)) > 0 ? a : b);
public static T MaxBy<T, TKey>(this IEnumerable<T> src, Func<T, TKey> key) => src.Aggregate((a, b) => Comparer<TKey>.Default.Compare(key(a), key(b)) > 0 ? a : b);
public static T MinBy<T, TKey>(this IEnumerable<T> src, Func<T, TKey> key, Comparer<TKey> keyComparer) => src.Aggregate((a, b) => keyComparer.Compare(key(a), key(b)) < 0 ? a : b);
public static T MinBy<T, TKey>(this IEnumerable<T> src, Func<T, TKey> key) => src.Aggregate((a, b) => Comparer<TKey>.Default.Compare(key(a), key(b)) < 0 ? a : b);

最新更新