编程题

属性结构数据打印

有一个表达树状结构的数据列表,示例如下:

id   parentId   name
1    0          AA
2    1          BB
3    1          CC
4    3          DD
5    3          EE
6    2          FF
7    2          GG
8    4          HH
9    5          II

数据节点描述:

interface TreeNode {
  id: number; // 节点 ID
  parentId: number; // 父节点 ID
  name: string; // 节点名称
}

请写一个函数 printTree(list: TreeNode[]): void 把输入的数据在控制台打印为一个有缩进的树形结构。上面的示例输出的结果如下:

AA
  BB
    FF
    GG
  CC
    DD
      HH
    EE
      II

可以有辅助函数, 可以扩展 TreeNode 数据结构字段

function printTree(list) {
  // 实现如下
  const len = list.length
  const childrens = {}, vals = {}

  for(let i = 0; i < len; i++) {
    let { id, parentId, name } = list[i]
    vals[id] = name
    if (childrens[parentId]) {
      childrens[parentId].push(id)
    } else {
      childrens[parentId] = [id]
    }
  }
  let root = list.find(item => item.parentId === 0)

  print(vals[root.id], childrens[root.id], 0)
  function print(name, ids, strLength) {
    console.log(' '.repeat(strLength) + name)
    if (!ids) return
    for(let id of ids) {
      print(vals[id], childrens[id], strLength + name.length)
    }
  }
}

千分位格式化

给出一个数字,如 12345.6789 ,返回格式化后的内容,如 12,345.678,9

function format(num) {
  let [a, b] = num.toString().split('.')
  let p = a.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
  let q = b?.split('').reverse().join('').replace(/(\d)(?=(?:\d{3})+$)/g, '$1,').split('').reverse().join('')
  if (!q) return p
  return p + '.' + q
}

React Input 表单组件

请完成 React 组件封装,能够实现如下图输入框功能封装,并且不失 input 原生组件能力

import React from 'react'

interface Props {
  value: string;
  defaultValue?: string;
  onChange?: (value: string) => any;
  maxLength?: number;
}

class CustomInput extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      currentLength: 0,
      value: props.defaultValue,
    }
  }

  componentDidUpdate(props) {
    if (props.value !== this.props.value) {
      this.setState({ value: props.value })
    }
  }

  onChange = value => {
    if (value.length > this.props.maxLength) return
    this.setState({ value, currentLength: value.length })
    this.props.onChange?.(value)
  }

  render() {
    const { maxLength, value, defaultValue } = this.props
    const { currentLength } = this.state
    return (
      <div>
        <input ref={e => { this.ref = e }} onChange={this.onChange} />
        <span>{`${currentLength}/${maxLength}`}</span>
      </div>
    )
  }
}