recherche

Maison  >  Questions et réponses  >  le corps du texte

python:怎样合并文档中有重复部分的行?

文档内容如下:

   (数据对)              (信息)
-----------------  ------------------------
  1         2         3        4       5
-----------------  ------------------------
pr333    sd23a2    thisisa    1001    1005
pr333    sd23a2    sentence    1001    1005
pr33w    sd11aa    we    1022    1002
pr33w    sd11aa    have    1022    1002
pr33w    sd11aa    adream    1033    1002
......

第 1, 2 列作为一个 数据对

如果前两列相同,判断后面的是否相同,如果不同就连接起来,合并成一行

如同下面的效果:

pr333    sd23a2    thisisa|sentence    1001    1005
pr33w    sd11aa    we|have|adream    1022|1033    1002
....

小白,不懂怎么做,只能想到用字典,好像又行不通,求各位大神帮忙

大家讲道理大家讲道理2886 Il y a quelques jours1171

répondre à tous(4)je répondrai

  • 阿神

    阿神2017-04-17 17:52:17

    Si vous souhaitez conserver l'ordre de sortie, vous devez utiliser OrderedDict. La clé utilise OrderedDict pour maintenir l'ordre. Les informations suivantes utilisent list pour maintenir l'ordre. être gâché, utilisez set pour maintenir l'ordre Bon choix

    .
    import re
    from collections import OrderedDict
    
    datas = OrderedDict()
    
    with open('info.txt') as f:
        for line in f:
            if not line.strip().startswith('pr'):
                continue
            items = re.split(r'\s+', line.strip())
            key = ' '.join(items[:2])
            if key not in datas:
                datas[key] = [[item] for item in items[2:]]
            else:
                for item, data in zip(items[2:], datas[key]):
                    data.append(item)
    
    for key, value in datas.items():
        print(key, *map('|'.join, value))

    répondre
    0
  • 阿神

    阿神2017-04-17 17:52:17

    Expliquez toutes les considérations pour ce code.


    La première est la commande. La commande ici comporte deux parties, l'une est l'ordre des lignes de sortie et l'autre est l'ordre après la fusion des éléments. Nous avons observé :

    pr333    sd23a2    thisisa    1001    1005
    pr333    sd23a2    sentence    1001    1005
    pr33w    sd11aa    we    1022    1002
    pr33w    sd11aa    have    1022    1002
    pr33w    sd11aa    adream    1033    1002

    devient :

    pr333 sd23a2 thisisa|sentence 1001 1005
    pr33w sd11aa we|have|adream 1022|1033 1002
    1. L'ordre des lignes de sortie est à prendre en compte : pr333 vient avant pr33w

    2. L'ordre après fusion des projets doit être pris en compte : thisisa vient avant la phrase

    Cela signifie que le type de données que nous utilisons doit pouvoir maintenir la commande


    La seconde est la rapidité. Nous savons tous que le type séquence est une recherche linéaire Pour plus d'efficacité, il est préférable d'utiliser le type mappage.

    Après trois considérations, comme l'a dit moling3650, OrderedDict est un bon choix. Cela peut résoudre le problème de la sortie de ligne, mais comme le projet de fusion n'a besoin d'utiliser que la clé et non la valeur, il est dommage d'utiliser OrderedDict. Cependant, il n'y a actuellement aucune option OrderSet dans la bibliothèque standard, donc je dois me contenter.

    1. Pour plus d'informations sur OrderedDict, veuillez vous référer à OrderedDict

    2. En fait, il existe une bibliothèque tierce OrderedSet
      ou vous pouvez l'implémenter vous-même, veuillez vous référer à OrderedSet (recette Python)


    Enfin, linkse7en a un très bon point. Pour ce genre de problème de traitement de documents, si vous savez lire et écrire en même temps, la lecture et le traitement en même temps seront certainement efficaces<🎜. > (car vous n'avez besoin de traiter le document qu'une seule visite)() et 討論請見評論部分 moling 大的觀點économiser des ressources (la sortie est terminée immédiatement, pas besoin de perdre de l'espace pour stocker les données). Cependant, étant donné que des paires de données en double peuvent apparaître sur les lignes , il est toujours nécessaire de dépenser plus de ressources pour assurer la stabilité.


    Code (Python3) :

    from collections import OrderedDict
    
    data = OrderedDict()
    
    DPAIR = slice(0,2)
    MSG = slice(2,None)
    
    with open('data.txt', 'r') as reader:
        for line in reader:
            line = line.strip()
            items = tuple(line.split())
    
            msgs = data.setdefault(items[DPAIR], [OrderedDict({}) for msg in items[MSG]])
            for idx, msg in enumerate(msgs):
                msg.setdefault(items[MSG][idx], None)
    
    for (dp1, dp2), msgs in data.items():
        print(dp1, dp2, *['|'.join(msg.keys()) for msg in msgs])


    J'expliquerai également la partie code (peut-être que mon écriture n'est pas la meilleure, mais je peux partager quelques expériences).

    Le premier est l'application de

    classe. slice

    En tant que programmeur Python, nous devrions être familiers avec le

    type de séquence le découpage.

    items[start:stop:step]

    peut en fait s'écrire ainsi :

    items[slice(start, stop, step)]
    
    # example
    items[:5]  可以寫成  items[slice(0,5)]
    items[7:]  可以寫成  items[slice(7,None)]

    Quels sont les avantages ?

    Nous pouvons utiliser cette fonctionnalité pour nommer des tranches. En prenant le code de cette question comme exemple, nous voulions à l'origine extraire la

    paire de données et les autres données.

    items = tuple(line.split())
    items[0:2]  # 這是用來做 key 的數據對
    items[2:]   # 這是其他的資料項

    Mais cette méthode n'est en fait pas assez claire pour être lue. Nous pouvons donner un nom à ces deux plages, donc :

    DPAIR = slice(0,2)
    MSG = slice(2,None)
    items[DPAIR] # 這是用來做 key 的數據對
    items[MSG]   # 這是其他的資料項

    Nous pouvons obtenir la valeur de

    d'une manière plus élégante et plus lisible. items


    La seconde est

    , cette fonction est assez pratique, par exemple : setdefault

    dic.setdefault(key, default_value)

    Si la valeur clé

    existe dans le dictionnaire (ou autre type de mappage correspondant), retournez key Sinon, le retour insérera automatiquement une nouvelle paire clé-valeur dic[key] dans le dictionnaire et renverra <🎜. >. dic[key] = default_value default_value

    La dernière chose que je veux partager est le démontage des tuples imbriqués :
    for (a, b), c, d in ((1,2) ,3, 4):
        print(a, b, c, d)  # 印出 1 2 3 4

    Cette technique peut être facilement utilisée pour démanteler des tuples imbriqués.


    Merci à tous de ne pas vous plaindre du fait que je parle trop...

    répondre
    0
  • 怪我咯

    怪我咯2017-04-17 17:52:17

    Est-il plus pratique d'utiliser des pandas ?

    import pandas as pd
    df = pd.read_csv('example.txt',sep=' ',header=None)
    df = df.astype(str) # 将数字转换为字符串
    grouped = df.groupby([0,1])
    result = grouped.agg(lambda x:'|'.join(x))

    Quatre lignes résoudront le problème
    J'ai d'abord enregistré le document sous le format example.txt

    répondre
    0
  • 高洛峰

    高洛峰2017-04-17 17:52:17

    from collections import defaultdict
    
    a = '''
    pr333 sd23a2 thisisa 1001 1005
    pr333 sd23a2 sentence 1001 1005
    pr33w sd11aa we 1022 1002
    pr33w sd11aa have 1022 1002
    pr33w sd11aa adream 1033 1002
    '''
    
    data = defaultdict(dict)
    keys = []
    
    for line in a.split('\n'):
        if not line:
            continue
        items = line.split()
        key = ' '.join(items[:2])
        keys.append(key)
        for i, item in enumerate(items[2:]):
            data[key][i] = data[key].get(i, []) + [item]
    for key in sorted(list(set(keys)), key=keys.index):
        value = data[key]
        print key,
        for i in sorted(value.keys()):
            vs = list(set(value[i]))
            vs.sort(key=value[i].index)
            print '|'.join(vs),
        print
    

    répondre
    0
  • Annulerrépondre