【问题标题】:Need an algorithm to group several parameters of a person under the persons name需要一个算法来将一个人的几个参数分组到一个人的名字下
【发布时间】:2010-05-11 19:42:02
【问题描述】:

我有一堆按字母顺序排列的名称,其中多个同名实例均按字母顺序排列,因此这些名称都组合在一起。在每个名称旁边,在昏迷之后,我有一个分配给他们的角色,每行一个名称-角色对,如下所示

姓名1,角色1
名称1,角色2
名称1,角色3
名称1,角色8
名称2,角色8
名称2,角色2
名称2,角色4
名称3,角色1
名称4,角色5
名称4,角色1
...
..
.

我正在寻找一种将上述 .csv 文件作为输入的算法,以以下格式创建输出 .csv 文件

name1,role1,role2,role3,role8
名称 2,角色 8,角色 2,角色 4
名称3,角色1
名称 4,角色 5,角色 1
...
..
.

所以基本上我希望每个名称只出现一次,然后在输入文件中所有名称和角色的名称旁边以 csv 格式打印角色。

算法应该与语言无关。如果它不使用 OOP 原则,我将不胜感激 :-) 我是新手。

【问题讨论】:

  • OOP 被禁止。可以使用数据结构吗?
  • 虽然问的不同,但最终结果几乎与以下内容重复:stackoverflow.com/questions/2748156/…
  • @Kenny - 没有数据结构。我一定很痛苦吧? @Jerry - 感谢您的链接,杰瑞。

标签: algorithm language-agnostic


【解决方案1】:

显然有一些格式错误,但这会让你开始。

var lastName = "";

do{
  var name = readName();
  var role = readRole();
  if(lastName!=name){
    print("\n"+name+",");
    lastName = name;
  }
  print(role+",");
}while(reader.isReady());

【讨论】:

  • 感谢 Stefan,感谢您的解决方案,但您的算法中的 lastName 何时会更新?
  • 我修补了 Stefan 的代码(希望你不介意)添加刷新lastName 内容的地方。
  • @Matthieu - 感谢您的澄清。
  • @Matthieu 谢谢!有人把我的注意力转移了,没有仔细看。
【解决方案2】:

如果你的语言有关联数组,这很容易做到:数组可以被任何东西(例如字符串)索引,而不仅仅是数字。有些语言称它们为“哈希”、“地图”或“字典”。

另一方面,如果您可以保证将姓名分组到您的示例数据中,那么 Stefan 的解决方案效果很好。

【讨论】:

    【解决方案3】:

    很遗憾您说它必须与语言无关,因为 Python 非常适合此:

    import itertools
    def split(s):
      return s.strip().split(',', 1)
    with open(filename, 'r') as f:
      for name, lines in itertools.groupby(f, lambda s: split(s)[0])
        print name + ',' + ','.join(split(s)[1] for s in lines)
    

    基本上,groupby 调用会获取所有具有相同名称的连续行并将它们组合在一起。

    现在想来,Stefan 的回答可能更有效率。

    【讨论】:

    • 非常神秘。我不能很好地理解它。什么是 lamda s:?
    • lambda s: split(s)[0] 是一个函数,它调用split(s) 然后返回返回元组的第一个元素——在本例中是名称,即行中的第一个元素。 itertools.groupby 使用该函数按名称对行进行分组。然后lambda s: split(s)[1] 返回该行的第二件事,即角色,该行用逗号将所有角色连接在一起。 (我真的只是出于好奇而发布它,这不是您要寻找的答案。)
    【解决方案4】:

    这是Java的解决方案:

    Scanner sc = new Scanner (new File(fileName));
    Map<String, List<String>> nameRoles = new HashMap<String, List<String>> ();
    while (sc.hasNextLine()) {
      String line = sc.nextLine();
      String args[] = line.split (",");
      if (nameRoles.containsKey(args[0]) {
        nameRoles.get(args[0]).add(args[1]);
      } else {
        List<String> roles = new ArrayList<String>();
        roles.add(args[1]);
        nameRoles.put(args[0], roles);
      }
    }
    
    // then print it out
    for (String name : nameRoles.keySet()) {
       List<String> roles = nameRoles.get(name);
       System.out.print(name + ",");
       for (String role : roles) {
         System.out.print(role + ",");
       }
       System.out.println();
    }
    

    通过这种方法,您可以使用如下随机输入:

    姓名1,角色1

    姓名3,角色1

    名称2,角色8

    名称1,角色2

    名称2,角色2

    名称4,角色5

    名称4,角色1

    【讨论】:

    • 感谢您的解决方案,但我无法理解 Map> nameRoles = new HashMap> ();意思是。
    • 另外,如果您能告诉我您遵循的逻辑,那将非常有帮助。
    • 它们是 java 的一些特定实现,但您可以在几乎所有其他编程语言中找到它。数据结构是这样的:想象您有一个包含 2 列的表,其中一列包含唯一键,另一列包含数据数组。每次你有一个像 name1 - role2 这样的新数据。您在列键中找到 name1(通过散列、循环......),然后您得到另一列中对应的数据数组。然后将 role2 添加到该数据数组中
    【解决方案5】:

    这是在 C# 中使用的,没有什么花哨的。它应该是不言自明的:

    static void Main(string[] args) 
    {
        using (StreamReader file = new StreamReader("input.txt"))
        {
            string prevName = "";
            while (!file.EndOfStream)
            {
                string line = file.ReadLine(); // read a line
    
                string[] tokens = line.Split(','); // split the name and the parameter
    
                string name = tokens[0]; // this is the name
                string param = tokens[1]; // this is the parameter
    
                if (name == prevName) // if the name is the same as the previous name we read, we add the current param to that name. This works right because the names are sorted.
                {
                    Console.Write(param + " ");
                }
                else // otherwise, we are definitely done with the previous name, and have printed all of its parameters (due to the sorting).
                {
                    if (prevName != "") // make sure we don't print an extra newline the first time around
                    {
                        Console.WriteLine();
                    }
                    Console.Write(name + ": " + param + " "); // write the name followed by the first parameter. The output format can easily be tweaked to print commas.
                    prevName = name; // store the new name as the previous name.
                }
            }
        }
    }
    

    【讨论】:

    • 感谢您的解决方案。这个实际上帮助我理解了我应该使用的算法,这是我从一开始就想要的。它很容易理解和不言自明。
    猜你喜欢
    • 1970-01-01
    • 2016-04-08
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    相关资源
    最近更新 更多