【问题标题】:How to add elements in custom Dictionary using C#?如何使用 C# 在自定义字典中添加元素?
【发布时间】:2016-07-16 17:09:46
【问题描述】:

我在 C# 中名为 Cluster 的类中有一个用于聚类目的的字典:

Dictionary<int, List<ClusterMember>>

int 代表cluster idList<ClusterMember>> 代表cluster id 中的成员ClusterMember 是另一个类.我在这里展示了整个代码结构:

public class ClusterMember
{
    public string _name { get; set; }
}

public class Cluster
{
    public Dictionary<int, List<ClusterMember>> _dic { get; set; }  

    public Cluster(int _id, List<ClusterMember> _clusMem)
    {
       _dic.Add(_id, _clusMem);
    }
}  

而我在这个方法中使用了这些类:

public static List<Cluster> DP_Cluster(List<string> _customer, double _alpha)
{
    var _currentClusters = 0; // current number of clusters i.e. "k"
    var _memberNumber = 0;    // running member number i.e. "n"
    //var _dic = new Dictionary<int, List<string>>();
    var _probOld = 0.0;
    var _probNew = 0.0;


    List<Cluster> _myClusters = new List<Cluster>();
    //Cluster _cluster = new Cluster(?);  
    // How to Add cluster using above classes
    // How to Add cluster Member using above classes  
    _myClusters.Add(_cluster);

    //_dic.Add(_currentClusters, _customer.ElementAt(_memberNumber));
    _currentClusters += 1;

    for(int _i = 1; _i < _customer.Count - 1; _i++)
    {
        if( _i <= _currentClusters)
        {
            _probOld = myClusters[_i].Members.Count / ((_i+1) - 1 + _alpha);
        }
        else
        {
            _probNew = _alpha / ((_i+1) - 1 + _alpha);
        }

        if(_probNew > _probOld)
        {
            // Add _customer.ElementAt(_memberNumber+=1) to New Cluster
            Cluster cluster = new Cluster( _currentClusters += 1 ); 
            myClusters.Add(cluster);
        }
        else
        {
            // Add _customer.ElementAt(_memberNumber+=1) to Old Cluster
        }
    }

    return myClusters;
}  

现在如何在for loop 中添加Dictionary_dic 对象?此外,我可能不得不多次将多个集群成员添加到同一个_id

  • 我可能会在迭代中向_id = 1 添加一个集群成员
  • 然后必须添加一个集群成员到另一个_id = 2 迭代,
  • 然后它可能会转而将另一个集群成员添加到相同的 id,即_id = 1,反之亦然。

此外,如果可以使用1(而不是0默认_dicindex)。

【问题讨论】:

  • 您能出示您的for loop 代码吗?
  • 我会考虑从 Cluster 类中删除您的集群字典,因为它实际上应该只封装单个集群及其功能。也许考虑创建一个 ClusterDictionary 类并在其中添加用于添加集群成员/删除集群成员的功能。
  • @kienct89 我已经展示了整个 method 包含 for loop 以及

标签: c# list dictionary nested add


【解决方案1】:

此外,我可能必须将多个集群成员添加到同一个 id 不止一次

您可以像这样检查每个循环迭代的键:

public void AddInCluster(int id, List<ClusterMember> _clusMem)
{
    if (_dic.ContainsKey(id))
    {
        foreach (var clusterMember in _clusMem)
        {
            _dic[id].Add(clusterMember);                    
        }
    }
    else
    {
        _dic.Add(id, _clusMem);
    }
}

或者您可以使用字典中的 TryGetValue:

public void AddInCluster(int id, List<ClusterMember> _clusMem)
{
    List<ClusterMember> members;
    if (_dic.TryGetValue(id, out members))
    {
        foreach (var clusterMember in _clusMem)
        {
            members.Add(clusterMember);
        }
    }
    else
    {
        _dic.Add(id, _clusMem);
    }       
}

而且,如果可以开始的话,对我来说会更有意义 集群 ID 为 1

如果将您的int 包装到ClusterId 类中,如果id 为0,该类可能会引发异常? 此外,您的 Cluster 类可以覆盖字典上的访问器运算符 [] 以在您的上下文中提供有意义的抽象(例如从 1 而不是 0 开始)

你也可以添加一个Get,就像你的Add一样检查这个id是否存在:

public List<ClusterMember> GetFromCluster(ClusterId id)
{
    if (_dic.ContainsKey(id))
    {
        return _dic[id];
    }

    throw new ClusterDoesNotContainsThisId(id);
}

【讨论】:

    【解决方案2】:

    对于Dictionaries 使用Add 方法怎么样?喜欢:

    if(needToAddNewCluster){
        _dic.Add(index, new List<ClusterMember>());
    }
    if(needToExtendCluster){
        _dic[index].Add(clusMem);
    }
    

    在此我假设needToAddNewCluster 检查_dic.ContainsKey(index)

    【讨论】:

      【解决方案3】:

      您可以向集群类添加方法

      public void AddToCluster(int id, ClusterMember member)
      {
          // checks if cluster with specific id is already in Dictionary
          if(!_dic.ContainsKey(id))
             _dic.Add(id,new List<ClusterMember>());
      
           _dic[id].Add(member);
      }
      

      你可以像这样在迭代中使用它

      int id = 1; // cluster id
      foreach(var m in members)
      {
         // adding members to cluster with id = 1
         cluster.AddToCluster(id,m);
      }
      

      更新

      我们还可以获得每个集群 ID 的列表计数,即每个集群 ID 的集群成员计数吗?

      你可以添加这两种方法

      // get members count for specific cluster id
      public int GetCount(int id)
      {
           return _dict[id].Count;
      }
      
      // get members count for all clusters
      public Dictionary<int,int> GetCounts()
      {
          return _dict.ToDictionary(k=>k.Key,v=>v.Value.Count);
      }
      

      你可以这样访问

      var counts = cluster.GetCounts();
      var c1Cnt=counts[1]; // 1 is cluster id
      

      【讨论】:

      • @stanke--在你的方法AddtoCluster我们如何扩展旧集群?
      • @stanke--我们也可以获得每个集群 ID 的列表计数,即每个集群 ID 的集群成员计数吗?
      • @maliks - 以什么方式扩展?
      • @stanke--extend 意味着将成员添加到现有集群 --- 也 _dic[id].Value.Add(member); 给出错误,即 不包含 Value 的定义
      • @maliks - 我更新了方法。扩展部分已经包含在第一种方法中
      【解决方案4】:

      我会稍微改变Culster 类的实现。 _dic 应该是带有初始化器的仅 getter 属性。根据通常的 .NET C# 命名约定,属性应该使用 PascalCase,因此我将其重命名为 Dic。 (更好的名称是MemberDictionaryMembers)。带下划线的 _camelCase 标识符通常用于字段。方法参数和局部变量都有驼峰式。

      然后添加用于添加一个或多个成员的新方法。两种方法都首先检查列表是否已经存在。如果存在,则将新成员添加到列表中,否则会创建一个使用新成员初始化的新列表,然后将其添加到字典中。

      public class Cluster
      {
          public Dictionary<int, List<ClusterMember>> Dic { get; }
              = new Dictionary<int, List<ClusterMember>>();
      
          // Initialize empty cluster.
          public Cluster()
          {
          }
      
          // Initialize cluster with one initial member.
          public Cluster(int key, ClusterMember member)
          {
              Add(key, member);
          }
      
          // Initialize cluster with many members.
          public Cluster(int key, IEnumerable<ClusterMember> members)
          {
              Add(key, members);
          }
      
          // Allows you to a one new member.
          public void Add(int key, ClusterMember member)
          {
              if (Dic.TryGetValue(key, out var memberList)) {
                  memberList.Add(member);
              } else {
                  memberList = new List<ClusterMember> { member };
                  Dic.Add(key, memberList);
              }
          }
      
          // Allows you to add many members.
          public void Add(int key, IEnumerable<ClusterMember> members)
          {
              if (Dic.TryGetValue(key, out var memberList)) {
                  memberList.AddRange(members);
              } else {
                  memberList = new List<ClusterMember>(members);
                  Dic.Add(key, memberList);
              }
          }
      }
      

      此实现将字典和列表的创建以及将成员添加到Cluster 类的细节委托给类。

      顺便说一句:字典使用键,而不是索引。


      我不知道你从哪里得到会员号,也不了解你的聚类算法;但是,我认为通过这些更改DP_Cluster 可能看起来像这样:

      public static List<Cluster> DP_Cluster(List<string> customers, double alpha)
      {
          double probOld = 0.0;
          double probNew = 0.0;
      
          var clusters = new List<Cluster>();
          Cluster currentCluster = null;
      
          for (int i = 0; i < customers.Count; i++) {
              if (i <= clusters.Count) {
                  probOld = clusters[i].Dic.Count / (i + alpha);
              } else {
                  probNew = alpha / (i + alpha);
              }
      
              if (probNew > probOld || currentCluster == null) {
                  currentCluster = new Cluster();
                  clusters.Add(currentCluster);
              }
              currentCluster.Add(_memberNumber, new ClusterMember { Name = customers[i] });
          }
      
          return clusters;
      }
      

      Cluster 中的一些构造函数和方法最终可能证明是多余的,因为我们总是一次添加一个客户。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-20
        • 1970-01-01
        • 2019-12-22
        相关资源
        最近更新 更多