正在创建JSON对象的置换?

2024-09-28 21:22:03 发布

您现在位置:Python中文网/ 问答频道 /正文

如果给我这样的输入:

[
    {
        "name":     "Robert",
        "city": "New York",
        "short":  "Bob"
    },
    {
        "name":     "Allison",
        "city": "Los Angeles",
        "short":  "Ally"
    },
    {
        "name":     "James",
        "city": "Chicago",
        "short":  "Jim"
    },
    {
        "name": "Hannah",
        "city":"Toronto",
    },
    {
        "name": "Elizabeth",
        "city": "London",
    }
]

我该如何生成这样的输出,从中得到所有可能的组合?你知道吗

[
    {"Robert": "New York", "Allison": "Los Angeles", "James": "Chicago", "Hannah": "Toronto", "Elizabeth": "London"},
    {"Bob": "New York", "Allison": "Los Angeles", "James": "Chicago", "Hannah": "Toronto", "Elizabeth": "London"},
    {"Robert": "New York", "Ally": "Los Angeles", "James": "Chicago", "Hannah": "Toronto", "Elizabeth": "London"},
    {"Bob": "New York", "Ally": "Los Angeles", "James": "Chicago", "Hannah": "Toronto", "Elizabeth": "London"},
    {"Robert": "New York", "Allison": "Los Angeles", "Jim": "Chicago", "Hannah": "Toronto", "Elizabeth": "London"},
    {"Bob": "New York", "Allison": "Los Angeles", "Jim": "Chicago", "Hannah": "Toronto", "Elizabeth": "London"},
    {"Robert": "New York", "Ally": "Los Angeles", "Jim": "Chicago", "Hannah": "Toronto", "Elizabeth": "London"},
    {"Bob": "New York", "Ally": "Los Angeles", "Jim": "Chicago", "Hannah": "Toronto", "Elizabeth": "London"},
]

请帮助我的家人。你知道吗


Tags: namecitynewrobertboblondonyorkallison
3条回答

我想你要找的是笛卡尔积,而不是组合,你能为每个人得到的每个可能的名字-城市对。也就是这些列表的笛卡尔积:

[('Robert', 'New York'), ('Bob', 'New York')]
[('Allison', 'Los Angeles'), ('Ally', 'Los Angeles')]
[('James', 'Chicago'), ('Jim', 'Chicago')]
[('Hannah', 'Toronto')]
[('Elizabeth', 'London')]

首先需要一个函数,将人名city short dict转换为姓名city/short city对的列表:

def pairs(person):
    names = [(person['name'], person['city'])]
    try:
        names.append((person['short'], person['city']))
    except KeyError:
        pass
    return names

现在,您需要将此应用于具有map或理解力的所有人:

allpairs = map(pairs, people)

现在您有了一些可以直接调用产品的功能:

results = itertools.product(*allpairs)

现在你只需要把每一对的列表变成一个dict:

output = [dict(result) for result in results]

然后你必须编写代码,将它们按你想要的奇怪顺序排列(也许你只是想把它们反向生成,然后再反向生成?),并以看起来有点像Python dict repr或JSON对象但实际上两者都不是的格式输出它。(另外,如果每个dict的顺序很重要,并且您没有使用python3.7或更高版本,则需要使用collections.OrderedDict而不是dict。)

这里有一个唯一的解决方案,它确实使用了内置函数combinations。但是,它确实假设输入是有效的JSON。你知道吗

[ map([ {(.name):.city},
        (if .short then {(.short):.city} else empty end) ] )
  | combinations
  | add ]

输出

[
  {
    "Robert": "New York",
    "Allison": "Los Angeles",
    "James": "Chicago",
    "Hannah": "Toronto",
    "Elizabeth": "London"
  },
  {
    "Robert": "New York",
    "Allison": "Los Angeles",
    "Jim": "Chicago",
    "Hannah": "Toronto",
    "Elizabeth": "London"
  },
  {
    "Robert": "New York",
    "Ally": "Los Angeles",
    "James": "Chicago",
    "Hannah": "Toronto",
    "Elizabeth": "London"
  },
  {
    "Robert": "New York",
    "Ally": "Los Angeles",
    "Jim": "Chicago",
    "Hannah": "Toronto",
    "Elizabeth": "London"
  },
  {
    "Bob": "New York",
    "Allison": "Los Angeles",
    "James": "Chicago",
    "Hannah": "Toronto",
    "Elizabeth": "London"
  },
  {
    "Bob": "New York",
    "Allison": "Los Angeles",
    "Jim": "Chicago",
    "Hannah": "Toronto",
    "Elizabeth": "London"
  },
  {
    "Bob": "New York",
    "Ally": "Los Angeles",
    "James": "Chicago",
    "Hannah": "Toronto",
    "Elizabeth": "London"
  },
  {
    "Bob": "New York",
    "Ally": "Los Angeles",
    "Jim": "Chicago",
    "Hannah": "Toronto",
    "Elizabeth": "London"
  }
]

如果您正在寻找一个Javascript解决方案,您需要自己的笛卡尔积函数,但其余的与上面的Python解决方案非常相似。这个函数使用了一个可变的笛卡尔函数,所以需要额外的步骤cartesian.apply(null, arr)。但除此之外,还应该直截了当:

const cartesian = (xs, ys, ...zs) => ys ? cartesian([].concat(...xs.map(x => ys.map(y => [].concat(x, y)))), ...zs) : xs; const toObj = xs => xs.reduce((a, b) => Object.assign(a, b), {}) const toNames = people => people.map(person => Object.keys(person) .filter(name => ['name', 'short'].includes(name)) .map(name => ({[person[name]]: person.city})) ) const nameCombos = people => cartesian.apply(null, toNames(people)).map(toObj) const people = [ { name: "Robert", city: "New York", short: "Bob" }, { name: "Allison", city: "Los Angeles", short: "Ally" }, { name: "James", city: "Chicago", short: "Jim" }, { name: "Hannah", city:"Toronto" }, { name: "Elizabeth", city: "London" } ] console.log(nameCombos(people))

相关问题 更多 >