1

各インデックスが名前であるリスト、または前の名前インデックスが予約されている部屋のリストがあるとします。

[["Bob"],["125A, "154B", "643A"],["142C", "192B"], ["653G"], 
["Carol"], ["95H", 123C"], ["David"], ["120G"]]

したがって、この場合、ボブには125A、154B、643A、152C、192B、653Gなどの部屋があります。

上記を次の形式にする関数を作成するにはどうすればよいですか。

[["Bob", "125A, "154B", "643A", "142C", "192B", "653G"], ["Carol"... 

[name]の次のインスタンスまで、基本的に[name]をすべての[部屋の予約のリスト]と連結します。私はリストを受け取り、リストが名前である場合、およびそれが部屋の予約のリストである場合に返す関数を持っているので、事実上次のようになります。TrueFalse

[True, False, False, False, True, False, True False]上記のリストについては、しかし、それが私にどのように役立つかはわかりません。リストに名前が含まれている場合、その名前は1つだけであると想定します。

4

5 に答える 5

1

次の方法を考えると

def is_name(x):
  return # if x is a name or not

簡単で短い解決策は、defaultdict


例:

from collections import defaultdict

def do_it(source):
  dd = defaultdict(lambda: [])
  for item in sum(source, []): # just use your favourite flattening method here
    if is_name(item):
      name = item
    else:
      dd[name].append(item)
  return [[k]+v for k,v in dd.items()]

for s in do_it(l):
  print s

出力:

['Bob'、 '125A'、 '154B'、 '643A'、 '142C'、 '192B'、 '653G']
['Carol'、 '95H'、 '123C']
['David'、 '120G' ]


ボーナス:

これは怠惰のためにジェネレーターを使用しています

import itertools 

def do_it(source):
  name, items = None, []
  for item in itertools.chain.from_iterable(source):
    if is_name(item):
      if name: 
        yield [name] + items
        name, items = None, []
      name = item
    else:
      items.append(item)
  yield [name] + items
于 2012-08-16T08:23:50.530 に答える
0

減らすことがあなたの答えです。あなたのデータはこれです:

l=[['Bob'], ['125A', '154B', '643A'], ['142C', '192B'], ['653G'], ['Carol'], ['95H', '123C'], ['David'], ['120G']]

あなたは、要素が名前であるかどうかを決定する関数をすでに持っていると言います。これが私のものです:

import re
def is_name(s):
  return re.match("[A-z]+$",s) and True or False

次に、reduceを使用すると、ワンライナーになります。

reduce(lambda c, n: is_name(n[0]) and c+[n] or c[:-1]+[c[-1]+n], l, [])

結果は次のとおりです。

[['Bob', '125A', '154B', '643A', '142C', '192B', '653G'], ['Carol', '95H', '123C'], ['David', '120G']]
于 2012-08-16T09:06:00.897 に答える
0

私は@uʍopǝpısdnの提案に強く同意すると言って、これを前置きします。ただし、セットアップで何らかの理由で変更できない場合は、これでうまくいくようです(きれいではありませんが)。

# Original list
l = [["Bob"],["125A", "154B", "643A"],["142C", "192B"], ["653G"], ["Carol"], ["95H", "123C"], ["David"], ["120G"]]
# This is the result of your checking function
mapper = [True, False, False, False, True, False, True, False]

# Final list
combined = []

# Generic counters
# Position in arrays
i = 0
# Position in combined list
k = 0

# Loop through the main list until the end.
# We don't use a for loop here because we want to be able to control the
# position of i.
while i < len(l):
  # If the corresponding value is True, start building the list
  if mapper[i]:
    # This is an example of how the code gets messy quickly
    combined.append([l[i][0]])
    i += 1
    # Now that we've hit a name, loop until we hit another, adding the
    # non-name information to the original list
    while i < len(mapper) and not mapper[i]:
      combined[k].append(l[i][0])
      i += 1

    # increment the position in our combined list
    k += 1


print combined
于 2012-08-16T08:06:13.333 に答える
0

リストに名前が含まれているか部屋が含まれているかに基づいてリストを取得し、TrueまたはFalseを返す関数がcontainsName()と呼ばれると仮定します。

def process(items):
  results = []
  name_and_rooms = []
  for item in items:
    if containsName(item):
      if name_and_rooms:
        results.append(name_and_rooms[:])
        name_and_rooms = []
      name_and_rooms.append(item[0])
    else:
      name_and_rooms.extend(item)
  if name_and_rooms:
    results.append(name_and_rooms[:])
  return results

これにより、フォローする部屋のリストがない場合でも名前が出力されます(例:[['bob']、['susan']])。

また、これは繰り返される名前をマージしません。例:[['bob']、['123']、['bob']、['456']]。それが必要な場合は、代わりに名前を一時的なdictに押し込み、各部屋のリストを値として指定する必要があります。そして最後にdictのキー値を吐き出します。しかし、それだけでは名前の順序は保持されません。名前の順序を維持したい場合は、名前の順序を含む別のリストを作成し、それをdictの値を吐き出すときに使用できます。

于 2012-08-16T08:06:49.887 に答える
0

本当に、あなたはこれのためにを使うべきですdict。これは、リストの順序が変更されないことを前提としています(名前は常に最初です)。

他の人が示唆したように、データ構造を再評価する必要があります。

>>> from itertools import chain
>>> li_combo = list(chain.from_iterable(lst))
>>> d = {}
>>> for i in li_combo:
...    if is_name(i):
...       k = i
...    if k not in d:
...       d[k] = []
...    else:
...       d[k].append(i)
... 
>>> final_list = [[k]+d[k] for k in d]
>>> final_list
[['Bob', '125A', '154B', '643A', '142C', '192B', '653G'], ['Carol', '95H', '123C'], ['David', '120G']]
于 2012-08-16T08:15:19.450 に答える