我怎样才能像在字典里一样对这些数据进行排序?

2024-04-26 09:39:58 发布

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

我有一个文本文件,其中有一些特定的产品,每个产品都有可供购买的商店。存储行以选项卡开始,而产品行不以字符开始

为了能够以更好的方式对其进行可视化,我想将其作为字典订购,并将商店名称作为键,后跟产品列表。例如:

{
    'Store1' : ['product1', 'product2'],
    'Store2' : ...
}

这是我为每种产品存储的数据示例:

  • 关键Ballistix BLT8G4D26BFT4K
    • 信息化
    • Bip
    • PC工厂
    • 我的盒子
  • 爱国者签名行PSD48G266681
    • PC Express
    • 索尔Uservi
  • 金斯敦KCP426NS6/8
    • 青年科技
    • Bip

预期的输出必须如下所示(打印精美):

{
    'Infor-Ingen' : ['Crucial Ballistix BLT8G4D26BFT4K'     ],
    'Bip'         : ['Crucial Ballistix BLT8G4D26BFT4K',
                     'Kingston KCP426NS6/8'                 ],
    'PC Factory'  : ['Crucial Ballistix BLT8G4D26BFT4K'     ],
    'MyBox'       : ['Crucial Ballistix BLT8G4D26BFT4K'     ],
    'PC Express'  : ['Patriot Signature Line PSD48G266681'  ],
    'Soluservi'   : ['Patriot Signature Line PSD48G266681'  ],
    'YouTech'     : ['Kingston KCP426NS6/8'                 ]
}

我有这个密码

from collections import OrderedDict

od = OrderedDict()
tienda, producto ,otra,aux,wea= [], [],[], [],[]

with open("rams.txt","r") as f:
    data = f.readlines()
    for linea in data:
        linea = linea.strip('\n')
        if '\t' in linea:
            tienda.append(linea.strip('\t'))
            aux.append(linea.strip("\t").strip("\n"))
        else:
            otra.append(aux)
            aux=[]
            producto.append(linea)
            aux.append(linea.strip("\n"))
    tienda = sorted(list(set(tienda)))
    for i in range(1,len(otra)):
        wea=[]
        for key in tienda:
            if key in otra[i]:
                wea.append(otra[i][0])
                od[key] = wea

现在的问题是,在打印字典时,它给了我这样的信息:

('Bip', ['Crucial Ballistix BLT8G4D26BFT4K ']), ('Infor-Ingen', ['Crucial Ballistix BLT2K8G4D26BFT4K ']), ('MyBox', ['Crucial Ballistix CT16G4DFD8266']),..)

Tags: in产品strippcappendauxbiplinea
2条回答

第一件事-关于在类上使用print(),请记住__str__()的普遍接受的用途(这就是print()所称的编织它的魔力)。它是一种人类可读的对象表示

因此OrderedDict的默认__str__()正是做了想要做的事。这不一定是您希望看到的特定的案例,但解决方案是认识到这最好作为OrderedDict的抽象

Python(作为一种面向对象的语言)的一部分功能是它能够基于当前类定义新的类,这些类可以添加任何您想要的额外行为或状态

对于您的情况,我将实现一个OrderedDict子类,并更改__str__()的输出以生成您需要的任何格式,例如:

from collections import OrderedDict

class ProductDb(OrderedDict):
    # Optional file to constructor to load immediately.

    def __init__(self, fspec=None):
        super().__init__(self)
        if fspec is not None:
            self.load(fspec)

    # Allow reloading at any point.

    def load(self, fspec):
        # Remove all existing information.

        self.clear()

        # For the Espanol-challenged amongst us:
        #     archivo = file
        #        este = this
        #       linea = line
        #    producto = product
        #      tienda = shop

        with open(fspec, 'r') as archivo:
            # To handle missing product line at start of file,
            # start with a fixed value. If first line IS a
            # product, it will simply replace this fixed value.
            # Then we process each line, sans newline character.

            este_producto = 'UNKNOWN'

            for linea in archivo.readlines():
                linea = linea.strip('\n')

                # Tienda lines start with tabs, producto lines do not.

                if '\t' in linea:
                    tienda = linea.strip('\t')

                    # Make NEW shops start with empty product list.
                    # Then we can just add current product to the
                    # list, not caring if shop was new.

                    if tienda not in self:
                        self[tienda] = []
                    self[tienda].append(este_producto)
                else:
                    # Change current product so subsequent
                    # stores pick that up instead.

                    este_producto = linea

        # Then, for each dictionary entry (store), de-dupe
        # and sort list (products), giving sorted products
        # within sorted stores. Use a copy of the keys, this
        # ensures no changes to the dictionary while you're
        # iterating over it.

        for key in list(self.keys()):
            self[key] = sorted(list(set(self[key])))

    def __str__(self):
        def spc(n): return " " * n

        # Get maximum store/product lengths for formatting.

        max_st = max([len(st) for st in self])
        max_pr = max([len(pr) for st in self for pr in self[st]])

        out = ""
        st_sep = f"{{\n{spc(4)}"
        for st in self:
            out += f"{st_sep}'{st}'{spc(max_st-len(st))} : "
            pr_sep = f"["
            for pr in self[st]:
                out += f"{pr_sep}'{pr}'"
                pr_sep = f",{spc(max_pr-len(pr))}\n{spc(max_st+10)}"
            out += f"{spc(max_pr-len(self[st][-1])+1)}]"
            st_sep = f",\n{spc(4)}"
        out += f"\n}}"

        return out

xyzzy = ProductDb('infile.txt')
print(xyzzy)

您会注意到,我还对文件加载程序方法做了一些相当大的更改,而不仅仅是将其作为类的方法

原始文件加载代码不需要像当前那样复杂。具体地说,您可以通过动态构建列表字典(希望代码中的注释能够解释事情)来摆脱所有这些临时列表

我使用了以下infile.txt测试文件(在车间生产线的开头有一个选项卡):

Crucial Ballistix BLT8G4D26BFT4K
    Infor-Ingen
    Bip
    PC Factory
    MyBox
Patriot Signature Line PSD48G266681
    PC Express
    Soluservi
Kingston KCP426NS6/8
    YouTech
    Bip

输出如下所示,与您的要求非常接近:

{
    'Infor-Ingen' : ['Crucial Ballistix BLT8G4D26BFT4K'    ],
    'Bip'         : ['Crucial Ballistix BLT8G4D26BFT4K',
                     'Kingston KCP426NS6/8'                ],
    'PC Factory'  : ['Crucial Ballistix BLT8G4D26BFT4K'    ],
    'MyBox'       : ['Crucial Ballistix BLT8G4D26BFT4K'    ],
    'PC Express'  : ['Patriot Signature Line PSD48G266681' ],
    'Soluservi'   : ['Patriot Signature Line PSD48G266681' ],
    'YouTech'     : ['Kingston KCP426NS6/8'                ]
}

解析文件时遇到一些问题。考虑到数据的格式,您应该坐下来试着理解您想要完成的是什么

该文件由行组成,这些行可被视为一组:

  • 包含产品名称的非缩进行
  • 然后是包含有产品的商店的缩进行

所以,当你阅读一个产品时,你应该记住这个产品,直到一个新产品被阅读

对于您阅读的每个商店,您应该将该产品添加到商店可用的产品列表中。为此,您需要一个字典,其中键是商店名称,值是产品

请记住,在尝试附加产品之前,必须检查字典中是否存在存储

解决这个问题的一个方法是:

products_by_store = dict()
with open("rams.txt","r") as f:
    cur_prod = None
    data = f.readlines()
    for linea in data:
        linea = linea.strip('\n')
        if '\t' in linea:
          linea = linea.strip('\t')
          if cur_prod:
            if not linea in products_by_store:
              products_by_store[linea] = [cur_prod]
            else:
              products_by_store[linea].append(cur_prod)
        else:
          cur_prod = linea
for k,v in products_by_store.items():
  print(k, v)

将返回以下输出:

Infor-Ingen ['Crucial Ballistix Tactical Tracer BLT8G4D26BFT4K']
Bip ['Crucial Ballistix Tactical Tracer BLT8G4D26BFT4K', 'Kingston KCP426NS6/8']
PC Factory ['Crucial Ballistix Tactical Tracer BLT8G4D26BFT4K']
MyBox ['Crucial Ballistix Tactical Tracer BLT8G4D26BFT4K']
PC Express ['Patriot Signature Line PSD48G266681']
Soluservi ['Patriot Signature Line PSD48G266681']
YouTech ['Kingston KCP426NS6/8']

当然,你应该根据自己的需要进行调整。你说了一些关于使用有序集合的事情。一旦一切就绪,对元素进行排序应该很简单

相关问题 更多 >