按“第一次出现的顺序”保存数据

题目考点

这道题主要考这几个点:

  1. 字典的使用
  2. 按“第一次出现的顺序”保存数据
  3. 字符串拆分与重新拼接
  4. 累加统计
  5. 输入处理

这题表面上像是在“打印商品和总价”,但真正的核心有两个:

第一,同名商品要合并统计价格总和
第二,输出顺序必须保持这个商品第一次出现的顺序


审题

输入是什么

第一行是一个整数 N,表示接下来有多少条购买记录。

后面 N 行,每一行都是:

item_name price

但这里要特别注意:

item_name 不是一定只有一个单词。

比如样例里有:

BANANA FRIES 12
POTATO CHIPS 30
APPLE JUICE 10

这说明:

  • 最后一个部分才是价格
  • 前面的所有部分拼起来,才是商品名

也就是说,一行不能简单理解成:

name, price = input().split()

因为像 "BANANA FRIES 12" 会被拆成:

['BANANA', 'FRIES', '12']

这时左边只有两个变量,就接不住三个部分。


输出是什么

输出每一种商品:

  • 按它第一次出现的顺序
  • 打印 item_name net_price

其中:

  • item_name 是商品名
  • net_price 是这个商品所有出现次数对应价格的总和

题目要求我们做什么

本质上就是:

把多条购买记录,按商品名分组,然后把同名商品的价格加起来,最后按第一次出现顺序输出。


容易忽略的点

这题最容易忽略的地方有两个:

1. 商品名可能有空格

不能直接写:

name, price = input().split()

因为商品名可能是 "APPLE JUICE""POTATO CHIPS" 这种多单词形式。

2. 要保持第一次出现顺序

如果只是单纯统计总价,不考虑顺序,事情很简单。
但题目要求“按照第一次出现顺序输出”,所以你存数据时就要考虑顺序问题。


思路提示

先不要急着写代码,先把过程想清楚。

你可以把每一行输入想成两部分:

第一部分是商品名,第二部分是价格。

但因为价格永远在最后,所以我们可以:

  1. 先把整行用 split() 拆成列表
  2. 取最后一个元素作为价格
  3. 把前面的元素重新用空格拼起来,得到商品名

然后,我们需要一个“能记住出现顺序”的字典:

  • 如果商品第一次出现,就把它放进去
  • 如果商品之前已经出现过,就把价格继续加上去

最后,再按照字典中的顺序逐个输出即可。


完整设计思路

现在把它展开成清晰的 4 步。

第一步:读入记录条数

先读入 N,表示后面有几行商品记录。


第二步:逐行处理每条记录

对于每一行,例如:

APPLE JUICE 10

先做:

parts = input().split()

得到:

['APPLE', 'JUICE', '10']

然后:

  • parts[-1] 是价格
  • parts[:-1] 是商品名的所有单词

于是:

price = int(parts[-1])
item_name = " ".join(parts[:-1])

这样就能得到:

item_name = "APPLE JUICE"
price = 10

这一步是整题最关键的输入处理。


第三步:用字典累计总价

准备一个字典来存:

{
    商品名: 总价
}

每读到一个商品时:

  • 如果它第一次出现,就直接存进去
  • 如果已经出现过,就把价格加上去

例如:

APPLE JUICE 10
APPLE JUICE 10

最后会变成:

"APPLE JUICE": 20

第四步:按顺序输出

最后遍历字典,把每个商品名和总价打印出来。

因为我们是按输入顺序逐步加入字典的,所以输出时自然就是“第一次出现的顺序”。


代码实现

这里我先给你一个很适合这道题的写法,使用 OrderedDict,也更贴近这道题原本想考的内容。

from collections import OrderedDict

n = int(input())
items = OrderedDict()

for _ in range(n):
    parts = input().split()
    price = int(parts[-1])
    item_name = " ".join(parts[:-1])

    if item_name in items:
        items[item_name] += price
    else:
        items[item_name] = price

for name, total_price in items.items():
    print(name, total_price)

运行演示

我们用题目样例来手动模拟一下。

输入:

9
BANANA FRIES 12
POTATO CHIPS 30
APPLE JUICE 10
CANDY 5
APPLE JUICE 10
CANDY 5
CANDY 5
CANDY 5
POTATO CHIPS 30

第 1 行

BANANA FRIES 12

拆分后:

parts = ['BANANA', 'FRIES', '12']
price = 12
item_name = 'BANANA FRIES'

字典变成:

{
    'BANANA FRIES': 12
}

第 2 行

POTATO CHIPS 30

字典变成:

{
    'BANANA FRIES': 12,
    'POTATO CHIPS': 30
}

第 3 行

APPLE JUICE 10

字典变成:

{
    'BANANA FRIES': 12,
    'POTATO CHIPS': 30,
    'APPLE JUICE': 10
}

第 4 行

CANDY 5

字典变成:

{
    'BANANA FRIES': 12,
    'POTATO CHIPS': 30,
    'APPLE JUICE': 10,
    'CANDY': 5
}

第 5 行

APPLE JUICE 10

APPLE JUICE 已经出现过,所以累加:

'APPLE JUICE': 10 + 10 = 20

字典变成:

{
    'BANANA FRIES': 12,
    'POTATO CHIPS': 30,
    'APPLE JUICE': 20,
    'CANDY': 5
}

后面几行继续累加

最后得到:

{
    'BANANA FRIES': 12,
    'POTATO CHIPS': 60,
    'APPLE JUICE': 20,
    'CANDY': 20
}

按顺序输出就是:

BANANA FRIES 12
POTATO CHIPS 60
APPLE JUICE 20
CANDY 20

方法总结

这类题以后你可以这样识别、这样下手。

一看到“按第一次出现顺序输出”

你就要立刻想到:

  • 不能只统计
  • 还要保留顺序
  • 适合用“有顺序的字典”

一看到“同名项目要合并”

你就要想到:

  • 用字典做“分组累计”
  • 键是名字
  • 值是总和

也就是这个模式:

if key in dic:
    dic[key] += value
else:
    dic[key] = value

一看到“商品名里可能有空格”

你就要想到:

  • 不能直接两个变量接收
  • 最后一个是数字
  • 前面的全部拼回去才是名字

这个模式非常重要:

parts = input().split()
price = int(parts[-1])
name = " ".join(parts[:-1])

这是这道题最核心的输入处理模板。


补充说明:为什么这里常用 OrderedDict

OrderedDictcollections 模块里的“有序字典”。

普通字典的重点是“键值对应”。
OrderedDict 除了保存键值,还专门强调“插入顺序”。

这道题题意正好是:

  • 遇到新商品时记住它第一次出现的位置
  • 后面再出现时只更新价格,不改变顺序

所以 OrderedDict 很适合。

在较新的 Python 版本里,普通 dict 也会保留插入顺序,所以很多时候也能写成:

n = int(input())
items = {}

for _ in range(n):
    parts = input().split()
    price = int(parts[-1])
    item_name = " ".join(parts[:-1])

    if item_name in items:
        items[item_name] += price
    else:
        items[item_name] = price

for name, total_price in items.items():
    print(name, total_price)

不过如果题目本身就在考 OrderedDict,那还是写 OrderedDict 更稳,也更符合出题意图。


本节小结

这道题本质不是难在“统计”,而是难在两件事:

第一,商品名可能有空格,所以要把最后一个元素当价格,前面重新拼接成名字。
第二,既要合并同名商品,又要保留第一次出现顺序,所以适合用 OrderedDict。

以后遇到类似题目,你可以优先套这个思路:

  1. 先拆输入
  2. 找出“键”和“值”
  3. 用字典累计
  4. 按保存顺序输出

练习

你可以先自己做这道同类型小练习。

题目

第一行输入一个整数 n
接下来 n 行,每行输入一个“书名”和“销量”,其中书名可能包含空格。
请你按书名第一次出现的顺序,输出每本书的总销量。

例如输入:

6
Harry Potter 3
Data Science 2
Harry Potter 4
Python Basics 5
Data Science 1
Harry Potter 2

期望输出:

Harry Potter 9
Data Science 3
Python Basics 5

提示

你可以直接套用这道题的方法:

  • split()
  • 最后一个元素当数字
  • 前面用 " ".join(...) 拼成名字
  • 用字典累计总和

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇