TLDR: 在 Draft.js 富文本框架中,根据文本的 type 可以将每一行文本划分为
'unstyled', 'header-one', 'header-two', ..., 'header-six', 'atomic', // 其他类型暂不考虑
其中,在处理 unstyled
文本时,
inlineStyleRanges
进行操作Decorator
实现的行内样式(比如 @某人),那么必须对 inlineStyleRanges
和 EntityRanges
先进行合并操作,即 根据 offset 排序数组(升序)已知 inlineStyleRanges
和 EntityRanges
都是 sorted.
根据对象的 offset 属性,对两个 sorted 的数组进行升序排序 ( Merge Sorted Arrays)
类型定义:
type InlineStyleRangesType = { offset: number, length: number, style: 'BOLD' | 'CODE' | 'ITALIC' | 'STRIKETHROUGH' | 'UNDERLINE', }[] type EntityRangesType = { offset: number, length: number, key: number, }[] type SortedArrayType = { offset: number, length: number, key?: number, style?: 'BOLD' | 'CODE' | 'ITALIC' | 'STRIKETHROUGH' | 'UNDERLINE', }[]
输入:
const a: InlineStyleRangesType = [ { offset: 1, length: 1, style: "BOLD" }, { offset: 9, length: 2, style: "ITALIC" }, ] const b: EntityRangesType = [ { offset: 4, length: 1, key: 0 }, { offset: 12, length: 1, key: 1 }, ]
输出:
[ { offset: 1, length: 1, style: "BOLD" }, { offset: 4, length: 1, key: 0 }, { offset: 9, length: 2, style: "ITALIC" }, { offset: 12, length: 1, key: 1 }, ]
// version 1 function mergeSortedArrays( inlineStyleRanges: InlineStyleRangesType, entityRanges: EntityRangesType ): SortedArrayType { const ranges = [] inlineStyleRanges.forEach((range) => ranges.push(range)) entityRanges.forEach((range) => ranges.push(range)) ranges.sort((a, b) => a.offset - b.offset) return ranges }
// version 2 function mergeSortedArrays( inlineStyleRanges: InlineStyleRangesType, EntityRanges: EntityRangesType ): SortedArrayType { const ranges = (inlineStyleRanges as SortedArrayType).concat(EntityRanges) ranges.sort((a, b) => a.offset - b.offset) return ranges }
// version 3 function mergeSortedArrays( inlineStyleRanges: InlineStyleRangesType, EntityRanges: EntityRangesType ): SortedArrayType { const ranges = [] let currentIndexEntity = 0; let currentIndexInlineStyle = 0; let currentIndexMerged = 0; while (currentIndexMerged < (inlineStyleRanges.length + EntityRanges.length)) { const isInlineStyleRangesExhausted = currentIndexInlineStyle >= inlineStyleRanges.length; const isEntityRangesExhausted = currentIndexEntity >= EntityRanges.length; // Case: next comes from inlineStyleRanges // inlineStyleRanges must not be exhausted, and EITHER: // 1) EntityRanges IS exhausted, or // 2) The current element in inlineStyleRanges is less // than the current element in EntityRanges if (!isInlineStyleRangesExhausted && (isEntityRangesExhausted || (inlineStyleRanges[currentIndexInlineStyle].offset < EntityRanges[currentIndexEntity].offset) )) { ranges[currentIndexMerged] = inlineStyleRanges[currentIndexInlineStyle]; currentIndexInlineStyle++; // Case: next comes from EntityRanges } else { ranges[currentIndexMerged] = EntityRanges[currentIndexEntity]; currentIndexEntity++; } currentIndexMerged++; } return ranges }
version 1 | version 2 | version 3 | |
---|---|---|---|
是否利用了 sorted 特性 | 否 | 否 | 是 |
时间复杂度 * | O(nlgn) | O(nlgn) | O(n) |
空间复杂度 | O(n) | O(n) | O(n) |
代码可读性 | ★★★★★ | ★★★★ | ★ |
* version 2 其实要优于 version 1 (常数倍)
![]() | 1 YadongZhang OP v2ex 似乎不支持 ts 语法高亮 |
![]() | 2 jatai 2020-10-21 18:06:33 +08:00 via Android ![]() 实际开发过程中, 即使没有任何技术难度, 也要牺牲代码的可读性, 为了显得不可替代 |
![]() | 3 raaaaaar 2020-10-21 18:08:08 +08:00 via Android ![]() 代码可读性真的和性能冲突吗?我有点疑惑,看那些经常炫技的代码,代码规范做好,命名,封装,注释,文档这么一套下来,真的会可读性低? |
![]() | 4 Leonard 2020-10-21 18:09:12 +08:00 ![]() 注释写得好就行 |
![]() | 5 gfreezy 2020-10-21 18:12:33 +08:00 ![]() 一行也就 1000 个字符串顶天了吧。啥排序在性能上都没啥区别吧。O(n^2) 在实际使用中都没啥区别吧? 如果确实追求性能,可以单独写个通用 mergesort 函数,贴个算法文档链接,再复杂的实现都没关系,一般都直接读文档就好了,没必要读代码。 |
![]() | 6 dreamapple 2020-10-21 18:24:41 +08:00 via Android 脚本语言直接调用内置 sort 和手写实现 merge 真的不知道哪个快,profile 一下说不定差别不大。实际项目亿级别的我选择 mapreduce |
![]() | 7 YadongZhang OP @gfreezy #5 好像是这样的,每行文本长度有限 |
8 xumng123 2020-10-21 20:45:09 +08:00 via iPhone 不是实时系统或者上百万的并发量,没啥区别 |
9 liyunlong41 2020-10-21 20:50:55 +08:00 via iPhone 突然想到力扣链表找环的问题,有快慢指针和哈希表两种做法,两者时间复杂度相同但是前者省内存,可是前者难于理解和维护,后者简单易懂,假如实际业务上有类似地方,我可能会用哈希表的做法。 |
![]() | 10 anguiao 2020-10-21 21:02:02 +08:00 via Android 如果是写偏底层的类库,应该考虑一下性能问题。 如果只是业务代码的话,在没有碰到性能瓶颈之前,个人觉得还是可读性比较重要。 |
![]() | 11 ipwx 2020-10-21 21:35:04 +08:00 ![]() 不是,现在前端程序员都这样了嘛,version 3 也叫不可读? |
![]() | 12 Sasasu 2020-10-21 22:32:29 +08:00 version 3 就是刻意写的很难懂,cpp 标准库版本 template<class InputIt1, class InputIt2, class OutputIt> OutputIt merge(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first) { for (; first1 != last1; ++d_first) { if (first2 == last2) { return std::copy(first1, last1, d_first); } if (*first2 < *first1) { *d_first = *first2; ++first2; } else { *d_first = *first1; ++first1; } } return std::copy(first2, last2, d_first); } |
![]() | 13 Sasasu 2020-10-21 22:36:44 +08:00 第一种就是刻意写的难懂,刻意使用下标,合并一个数组用光的条件到主循环里,合并判断条件到控制里 ``` template<class InputIt1, class InputIt2, class OutputIt, class Compare> OutputIt merge(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Compare comp) { for (; first1 != last1; ++d_first) { if (first2 == last2) { return std::copy(first1, last1, d_first); } if (comp(*first2, *first1)) { *d_first = *first2; ++first2; } else { *d_first = *first1; ++first1; } } return std::copy(first2, last2, d_first); } ``` ref https://en.cppreference.com/w/cpp/algorithm/merge |
![]() | 14 beidounanxizi 2020-10-22 00:54:37 +08:00 怎么说吧 premature optimize 是不可取的,lgN 也要看基数 N 啊 N 100 内 有区别嘛? |
![]() | 15 YadongZhang OP @beidounanxizi #14 复杂度说的是 asymptotic analysis |
![]() | 16 YadongZhang OP |
![]() | 17 YadongZhang OP @ipwx #11 edge cases 的考量 |
18 islxyqwe 2020-10-22 08:17:49 +08:00 ![]() 建一个 O(n)的<T>(a:T[],b:T[],cmp:(x:T,y:T)=>number):T[]然后调用 |
![]() | 19 gimp 2020-10-22 08:25:17 +08:00 |
![]() | 20 Nugine0 2020-10-22 09:07:18 +08:00 via Android ![]() 合并排序数组不是基础算法吗?应该有现成的轮子。 如果没有轮子,函数上面注释写清楚,加几个测试,没人会关心里面代码可不可读。 |
![]() | 21 bleepbloop 2020-10-22 09:57:57 +08:00 工作好几年了,从没遇到数据量大到需要刻意优化算法的地步,可能我太菜了吧 |
22 py2ex 2020-10-22 10:28:44 +08:00 以为 lgn 是什么新词,原来是 log N |
![]() | 23 YadongZhang OP @py2ex #22 CLRS 3e, Chap.1, Sec.3.2, P57 By equation (3.15) 换底公式, changing the base of a logarithm from one constant to another changes the value of the logarithm by only aconstant factor, and so we shall often use the notation “lg n” when we don’t care about constant factors, such as in O-notation. |
24 shadeofgod 2020-10-22 12:55:07 +08:00 合并两个有序数组的也可以很容易写出兼顾可读性的写法吧? |
25 shadeofgod 2020-10-22 12:55:52 +08:00 ![]() |