V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  wxf666  ›  全部回复第 29 页 / 共 31 页
回复总数  602
1 ... 21  22  23  24  25  26  27  28  29  30 ... 31  
2022-07-22 23:57:13 +08:00
回复了 MajestySolor 创建的主题 程序员 问个正则匹配的低端问题
仅捕获想要的字符串:

[^.]*$
2022-07-22 23:53:57 +08:00
回复了 MajestySolor 创建的主题 程序员 问个正则匹配的低端问题
$ sed 's/^.*\.//' <<<'dkfj.wer.dkfjj.sldkf'

输出:
sldkf
@ranxi 按理说你都能用 python 了,sqlite 是内置的标准库,应该是用得了的

# 根据 O2 构造 hash 表(字典)
with open(r'O2.txt', encoding='utf-8') as fp:
   table = dict((row.split('\t') for row in fp))

# O1 逐行替换并输出
with open(r'O1.txt', encoding='utf-8') as in_fp, open(r'out.txt', 'w', encoding='utf-8') as out_fp:
   for row in in_fp:
     cols = row.split('\t')
     cols[2] = table[cols[2].rstrip('\n')]
     out_fp.write('\t'.join(cols))

内存若不够,考虑构造 hash 表时,仅将 hash(str) 作为键名,然后 cols[2] = table[hash(cols[2].rstrip('\n'))] ?
有意思,也来写个 bash 版的

1. 默认去除前面的 1.1.2 、doc.math 之类的键名
2. 允许不按顺序指定目录,如此顺序可打乱:1 、1.1 、1.2 、1.2.1 、1.2.2
3. 父目录不存在,会在另一指定地方创建:1 、1.2.1 (不存在 1.2 ,所以 1.2.1 不会在 1 之下)

#!/bin/bash

declare -a SEP=('.' ' ')
declare -r WORK_DIR='./'
declare -r DANG_DIR='./dangling/'
declare -r EXCLUDE_KEY=yes # 若要包含 1.1.2 之类的键名,设为空字符串

declare -A dict=([${SEP[0]}]=$WORK_DIR)

sed '/^$/d' <<EOF | sort |
doc.eng 英语
doc 考研资料
doc.math 数学
doc.movie 电影

2.3.1 ???
2.3.1.1 !!!
2.2.1 Beyond
2 音乐
2.2 粤语
2.1.2 张震岳
2.1.1 周杰伦
2.1 华语
EOF
while read -r path; do
   key=${SEP[0]}${path%%"${SEP[1]}"*}
   parent=${key%"${SEP[0]}"*}
   dict[$key]=${dict[${parent:-${SEP[0]}}]:-$DANG_DIR}${path#${EXCLUDE_KEY:+*${SEP[1]}}}/
   echo "${dict[$key]}"
done | tee /dev/stderr | xargs -d $'\n' mkdir

输出并创建:

./音乐 /
./音乐 /华语 /
./音乐 /华语 /周杰伦 /
./音乐 /华语 /张震岳 /
./音乐 /粤语 /
./音乐 /粤语 /Beyond/
./dangling/???/
./dangling/???/!!!/
./考研资料 /
./考研资料 /英语 /
./考研资料 /数学 /
./考研资料 /电影 /
2022-07-22 13:10:24 +08:00
回复了 iamhrh2 创建的主题 正则表达式 ep 求一个数字和单位的正则
@iamhrh2 放多点“有些数字和英文一起的不是单位,不需要空软空格”的例子出来呗?
2022-07-21 19:24:47 +08:00
回复了 cmxzj 创建的主题 问与答 大表更新
@v2eb 第二个子查询( select 1 from B where A.colc=B.cold and colb is not null ),

为什么不能在扫描表 B 的时候,顺带过滤掉呢?

难道是有 B.colb is not null ,某个索引就失效了吗?

按理说,表 B 是驱动表,应该是全表扫描的?

就算要分批查询,也应先过滤掉再取出来,而不是取出来再过滤掉?
2022-07-21 19:07:13 +08:00
回复了 cmxzj 创建的主题 问与答 大表更新
@cmxzj 我感觉 #3 的语句应该是很快的?分批操作,实际没有减少数据量,反而增加了数据传输的损耗
2022-07-21 19:03:39 +08:00
回复了 cmxzj 创建的主题 问与答 大表更新
@gy123 咋会不走主键和索引呢

#3 的语句,我觉得流程应该是:

1. 扫描表 B ,过滤掉 B.colb 为 null 的行
2. 表 B 剩余的行,每行查索引 A.colc ,看是否存在值 B.cold
3. 若存在,从 A.colc 覆盖索引获取 表 A 的主键 ID ,再定位到表 A 的行记录,更新数据

如果说 update set limit 存在不足,就是表 B 已更新的行,每次都还要再检查一遍吧

加个 update set where B.id > ? limit 就好,但 mysql 好像没有 update returning ,无法确定上一次更新了哪些行
2022-07-21 17:47:00 +08:00
回复了 cannotfindobject 创建的主题 Java 咨询一下大家 activiti 几百万数据查询慢怎么办
为何不先加 ASSIGNEE_索引试试呢?
2022-07-21 17:43:17 +08:00
回复了 cmxzj 创建的主题 问与答 大表更新
@L0L 数据库新手求问,能不能不查出来(有传输数据的损耗),直接 update set limit ?

分批的作用,就是为了不一直堵塞,是嘛?
2022-07-21 17:08:53 +08:00
回复了 cmxzj 创建的主题 问与答 大表更新
这样?语句等价不?

update A join B on A.colc = B.cold and B.colb is not null
set A.cola = B.colb
2022-07-21 16:24:20 +08:00
回复了 PEax 创建的主题 Python 新手请教,关于操作列表的问题
@PEax 这样?

def sum_of_squares(items):

   def square(n: int):
     time.sleep(1)
     return n ** 2

   with ThreadPoolExecutor(max_workers=4) as executor:
     return sum(executor.map(square, items))

if __name__ == '__main__':
   print(sum_of_squares(range(1, 10 + 1))) # 1^2 + 2^2 + ... + 10^2
2022-07-20 19:27:51 +08:00
回复了 tool2d 创建的主题 问与答 有谁考虑过用移动硬盘当主力盘使用?
@512357301 叠瓦盘写放大有多严重?写 1MB 等于写 100MB ?
数据库新手求问,多大规模的表,就考虑冗余呢?

总不至于整个用户表就十几 MB ,也搞个冗余吧?估计数据库都缓存它们到内存了
原因 @zhlxsh #1 和 @foam #2 说了,解决方法 @foam #2 说了,我来扩展下思路


在通过『|』『()』『$()或``』启动的 subshell 中修改变量,只会在 subshell 中生效,不会影响 parent shell:
```bash
declare -i total=0

sum() {
   for i in {1..3}; do
     total+=i
   done
   printf '%4s: %d\n' "$1" "$total"
}

sum '|' | cat
(sum '()')
echo "$(sum '$()')"
echo "外部: $total"
```


结果,三种方式启动的 subshell ,都计算得 total=1+2+3=6 ,但实际都未修改外部的 total:
```
  |: 6
 (): 6
$(): 6
外部: 0
```


若要修改,就要在同一个 shell 环境中。对于『|』,可以尽量用『<<<』『< <()』等代替:
```bash
# seq 3 |
while read -r i; do
   total+=i
done < <(seq 3)
```


如果要捕捉输出,就想办法赋值到某个变量中(如 @foam #2 利用的 printf -v )。但归根结底,还是利用了 bash 的『动态作用域』。

bash 手册说,变量对自身及调用的子函数可见
> variables are visible only to the function and the commands it invokes

函数中使用了某个变量,先在自身找,找不到则在上一层调用者中找,一直到全局作用域
> visible variables and their values are a result of the sequence of function calls that caused execution to reach the current function. The value of a variable that a function sees depends on its value within its caller, if any, whether that caller is the "global" scope or another shell function


1. 所以,简单地,可以直接约定,子函数输出到 out 变量中,调用者直接用 out 变量
```bash
count=1

counter() {
  (( count++ ))
   out='test' # 自身找不到 out ,就在调用者 main 中找到 out 再赋值
}

main() {
   local out
   counter
   echo "count: $count, out: $out"
}

main  # 输出:count: 2, out: test
```


2. 将『要赋值到哪个变量』作为参数 /环境变量,传递给子函数,子函数自己想办法赋值

2.1 使用 @foam #2 说的 printf -v

2.2 使用『引用』
```bash
count=1
global_out=

counter1() {
  # 本函数内,out 是『名为「$1 的值」的变量』的引用(可同名,外部作用域的同名变量暂时被隐藏)
  # 如,out 是 main_out 的引用。对 out 的操作,实际是对 main_out 操作(自身找不到 main_out ,就在 main 找)
   declare -n out=$1; shift
  (( count++ ))
   out='test1'
}

counter2() {
  # 本函数内,out 是『名为「$out 的值」的变量』的引用
  # 右边的 out 是调用者临时扩充的环境变量,如 global_out (自身、main 找不到 global_out ,就在全局作用域找)
   declare -n out=$out
  (( count++ ))
   out='test2'
}

main() {
   local main_out
   counter1 main_out  # 作为参数传递
   out=global_out counter2  # 作为临时环境变量传递(综合觉得这种调用好看)
   echo "count: $count, main_out: $main_out, global_out: $global_out"
}

main  # 输出:count: 3, main_out: test1, global_out: test2
```
2022-07-19 20:19:20 +08:00
回复了 huntley 创建的主题 问与答 有没有自动生成 pdf 书签(目录)的软件?
@Juszoe 非扫描件,一般不都自带书签吗。。
2022-07-19 20:16:42 +08:00
回复了 huntley 创建的主题 问与答 有没有自动生成 pdf 书签(目录)的软件?
上面改成:

手动整理出下表,……
2022-07-19 20:15:40 +08:00
回复了 huntley 创建的主题 问与答 有没有自动生成 pdf 书签(目录)的软件?
自动搜集并生成书签的不知道

手动把诸如下表,转换成目录,并嵌入 pdf ,还是可以写个小脚本解决的

页码 层级 标题
  1    0  封面
  2    0  第一章
  3    1  第一章·第一节
……

关键命令:pdftk update_info_utf8
2022-07-16 22:41:44 +08:00
回复了 blankmiss 创建的主题 Python 刚撸 Python ,问个问题
你放点需求出来呗,说不定 Python 自身的语言特性都能满足你了
@brader 我试了下,大致有以下结论:

1. 即使我用 text 类型存 "1,2,3,…"( latin1 编码),无论是 700 / 7000 字节,find_in_set 都是 index

看来 MySQL 还不足够聪明优化 find_in_set

我还以为会生成个临时表,然后 FROM b JOIN a ON a.id IN tmp_table_of_a_ids 呢。。


2. JSON_TABLE 根据 "1,2,3,…" 生成表,再 join 表 a 是 eq_ref ,效率看来不错


3. 表 b 即使插入两行有 7000 字节的 ids 的行记录,也都在同一页( 16KB ),不用担心查找溢出页导致的效率问题


4. 你说的方法二(新增 C 表),我试了下,插入一千万行(a_id, b_id),磁盘占用 272.8 MB ,平均每行占用约 29 字节

看了下书,主要是每行数据额外记录了(记录头信息 5 字节 + 事务 ID 列 6 字节+ 回滚指针列 7 字节)= 20 字节,然后才是 (int, int) 的 8 字节,所以 C 表其实空间利用率很低

若是用 "1,2,3,…" 存储,即使每个 a_id 是 8 个数字+1 个逗号,一千万个记录也才 9 * (10 ^ 7) / (1 << 20) ≈ 85.8 MB

可即使是 85.8 MB ,楼主也说“计算量小,但是耗地方”

所以 C 表更不符合楼主要求


SET SESSION group_concat_max_len = 8192;
SET SESSION cte_max_recursion_depth = 2048;

CREATE TABLE `a` (
 `id` int NOT NULL AUTO_INCREMENT,
 `time` date NOT NULL,
 `data` int NOT NULL,
 `user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

CREATE TABLE `b` (
 `id` int NOT NULL AUTO_INCREMENT,
 `user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
 `sum_data` int NOT NULL,
 `a_ids` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

INSERT INTO a (time, data, user)
WITH RECURSIVE
  generate_series(i) AS (
   SELECT 0
   UNION ALL
   SELECT i+1 FROM generate_series WHERE i < 1600
 )
SELECT DATE_ADD('2021-01-01', INTERVAL i DAY), i + 1, 'a'
  FROM generate_series
WHERE i < 199  -- ids 长度为 2*9(1~9,) + 3*90(10~99,) + 4*100(100~199,) -1(末尾逗号) = 687 B
UNION ALL
SELECT DATE_ADD('2021-01-01', INTERVAL i DAY), i + 1, 'b'
  FROM generate_series
WHERE i <= 1760 - 200  -- ids 长度为 4*800(200~999,) + 5*761(1000~1760,) -1 = 7004 B
UNION ALL
SELECT DATE_ADD('2021-01-01', INTERVAL i DAY), i + 1, 'c'
  FROM generate_series
WHERE i <= 3240 - 1761; -- ids 长度为 5*1480(1761~3240,) -1 = 7399 B

INSERT INTO b (user, sum_data, a_ids)
SELECT user, sum(data), GROUP_CONCAT(id)
  FROM a
GROUP BY user;

EXPLAIN
SELECT a.id
  FROM b
  JOIN a ON FIND_IN_SET(a.id, b.a_ids)
WHERE b.user = 'c';

EXPLAIN
SELECT a.*
  FROM b,
    JSON_TABLE(
      CONCAT('[', b.a_ids, ']'),
      '$[*]' COLUMNS (id INT PATH '$')
    ) AS ids
  JOIN a USING(id)
WHERE b.user = 'c';


C 表测试:

SET SESSION cte_max_recursion_depth = 1 << 31;

CREATE TABLE `c` (
 `a_id` int NOT NULL,
 `b_id` int NOT NULL,
  PRIMARY KEY (`a_id`, `b_id`)
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

INSERT INTO c
WITH RECURSIVE
  generate_series(i) AS (
   SELECT 1
   UNION ALL
   SELECT i+1 FROM generate_series WHERE i <= 10000000
 )
SELECT i, i
  FROM generate_series;
1 ... 21  22  23  24  25  26  27  28  29  30 ... 31  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5106 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 42ms · UTC 03:41 · PVG 11:41 · LAX 20:41 · JFK 23:41
Developed with CodeLauncher
♥ Do have faith in what you're doing.