C# - 将对象分区到不同大小的分区

时间:2018-04-24 21:49:33

标签: c# .net cluster-analysis

我有一个非常大的对象列表(我自己定义的一个类)。我需要将此列表分成许多不同大小的不同分区。分区甚至可以只包含一个对象。基本上我试图根据这些对象之间的相似性来聚类这个列表。

以下是我的代码示例:

    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>();
    }

他们需要根据对象在其输入中的匹配数量(百分比)进行分区。名单。我希望能够限制分区的大小。

1 个答案:

答案 0 :(得分:0)

我认为没有一种有效的方法可以使用LINQ来执行此操作,但您可以遍历所有Foo并根据每个Foo的相似程度创建存储桶桶的内容,当相似度太低时创建一个新桶。我使用每个Foo的平均值和一个桶中的所有Foo作为单个Foo和一个桶(List<Foo>)之间的相似性,并找到了带有最高相似度。

假设有一个函数用于计算两个Foo之间的相似性(我使用了常见inputs成员的数量除以inputs的最大数量),你将它们放入桶中:< / p>

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我使用了我已经定义的扩展方法来查找max:

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);