Изменение значений дубликатов в многомерном списке в Python - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть список списков, подобных этому:

[[10000, 10001, 10002, 115050, 11506,11786,11787, 11788], [12553,12554,10001,10002], [9500, 9501, 9502, 9503, 9759, 9760, 9761, 11778,11779, 11780, 11781,11782, 12112, 12113]]

Что я хочу сделать, так это найти дублирующиеся значения, которые есть в этих списках, и изменить их на 1 или 2 при необходимости, поэтомучто не будет дубликатов или совпадений вообще.Я не могу изменить их на случайные значения, потому что они являются пиксельными значениями, и их огромное изменение исказит мой результат.

Я пробовал что-то вроде этого:

even = [[10000, 10001, 10002, 115050, 11506,11786,11787, 11788], [12553,12554,10001,10002], [9500, 9501, 9502, 9503, 9759, 9760, 9761, 11778,11779, 11780, 11781,11782, 11788, 11789, 12112, 12113]]
if(len(even)>1):
        inter = []
        for i in range(len(even)-1):
            #intersections = [set(even[i]).intersection(even[j]) for j in range(i+1, len(even)) ]
            for j in range(i+1, len(even)-1):
                intersect = list(set(even[i]).intersection(even[j]))
                if len(intersect)>0:
                    for inte in intersect:
                        even[j][even[j].index(inte)] =even[j][even[j].index(inte)]+1
                        print("we changed the value here", index)
        print(even)

Это вряд ли и приличнорешение, потому что оно терпит неудачу в этом самом примере.Я пытался сделать это с NumPy также.

length = len(sorted(even,key=len, reverse=True)[0])
y=np.array([xi+[None]*(length-len(xi)) for xi in even])
print( y, even)
y[:,1:] *=(np.diff(y,axis=1)!=0)

Однако этот код изменит дублирующиеся значения на 0, чего я не желаю.Любая помощь могла бы быть полезна.

Две вещи, на которые следует обратить внимание: ни в одном из списков внутри списка не должно быть повторяющихся значений, а измененное значение не должно иметь огромной разницы, 1,2 + или - в зависимостипосле, как мы можем уменьшить дублирование. Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Вот решение на месте:

def dedupe(lol):
    seen = set()
    for lst in lol:
        for ii, val in enumerate(lst):
            while val in seen:
                val += 1
            lst[ii] = val
            seen.add(val)

А вот генератор, который не изменяет вход:

def dedupe(lol):
    seen = set()
    for lst in lol:
        new = []
        for val in lst:
            while val in seen:
                val += 1
            new.append(val)
            seen.add(val)
        yield new

Вы можете использовать его как print(list(dedupe(l)).

0 голосов
/ 22 сентября 2018

Вы можете создать замыкание и вернуть функцию для применения к каждому элементу, который запоминает все элементы, которые были замечены.

def f():
  seen = set()        # Thing that sees all
  def g(a):           # New function that will refer to `seen`
    while a in seen:
      a += 1          # Keep adding one until we find one not in `seen`
    seen.add(a)
    return a
  return g            # Return the function that remembers `seen`

t = f()

even = [[1, 2], [2, 3], [4, 7]]

# not apply `t` ourselves
# neither `t` nor `f` need to know about the structure of `even`
[[t(x) for x in row] for row in even]

[[1, 2], [3, 4], [5, 7]]

Мы можем сделать этот шаг дальше и создать генератор, которыйОбходит произвольно вложенные списки

from collections.abc import Iterable

def h(i, t=None):

  if t is None:
    t = f()

  for x in i:
    if isinstance(x, Iterable) and not isinstance(x, str):
      yield [*h(x, t)]
    else:
      yield t(x)

Работает ли он на even?

[*h(even)]

[[1, 2], [3, 4], [5, 7]]

Что насчет чего-то более сложного?

[*h([1, 2, [1, 2], 3, 4, 9, [1, [20, 21, 21]]])]

[1, 2, [3, 4], 5, 6, 9, [7, [20, 21, 22]]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...