webDevInterviewQuestions/algorithm/02-array-string.md
2026-01-19 09:34:13 +08:00

3.2 KiB
Raw Blame History

数组与字符串操作

1. 数组去重(多种方法)

// 方法1: Set
const unique1 = arr => [...new Set(arr)];

// 方法2: filter + indexOf
const unique2 = arr => arr.filter((v, i) => arr.indexOf(v) === i);

// 方法3: reduce
const unique3 = arr => arr.reduce((acc, v) => acc.includes(v) ? acc : [...acc, v], []);

// 方法4: 对象数组按属性去重
const uniqueByKey = (arr, key) => {
  const map = new Map();
  arr.forEach(item => !map.has(item[key]) && map.set(item[key], item));
  return [...map.values()];
};

2. 扁平化数组

// 递归实现
function flatten(arr, depth = Infinity) {
  return arr.reduce((acc, val) => {
    return acc.concat(
      Array.isArray(val) && depth > 0 ? flatten(val, depth - 1) : val
    );
  }, []);
}

// 迭代实现(使用栈)
function flattenIterative(arr) {
  const stack = [...arr];
  const result = [];
  while (stack.length) {
    const item = stack.pop();
    Array.isArray(item) ? stack.push(...item) : result.unshift(item);
  }
  return result;
}

// 原生方法
arr.flat(Infinity);

3. 字符串反转

const reverse = str => str.split('').reverse().join('');

// 或者使用扩展运算符
const reverse2 = str => [...str].reverse().join('');

4. 判断回文

const isPalindrome = str => {
  const clean = str.toLowerCase().replace(/[^a-z0-9]/g, '');
  return clean === clean.split('').reverse().join('');
};

// 双指针法
const isPalindrome2 = str => {
  const s = str.toLowerCase().replace(/[^a-z0-9]/g, '');
  let left = 0, right = s.length - 1;
  while (left < right) {
    if (s[left++] !== s[right--]) return false;
  }
  return true;
};

5. 最长公共前缀

function longestCommonPrefix(strs) {
  if (!strs.length) return '';
  
  let prefix = strs[0];
  for (let i = 1; i < strs.length; i++) {
    while (strs[i].indexOf(prefix) !== 0) {
      prefix = prefix.slice(0, -1);
      if (!prefix) return '';
    }
  }
  return prefix;
}

// 示例: ["flower","flow","flight"] => "fl"

6. 模板字符串解析

function render(template, data) {
  return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
    return data[key] !== undefined ? data[key] : match;
  });
}

// 支持嵌套属性
function renderDeep(template, data) {
  return template.replace(/\{\{(.+?)\}\}/g, (match, path) => {
    const keys = path.trim().split('.');
    let value = data;
    for (const key of keys) {
      value = value?.[key];
      if (value === undefined) return match;
    }
    return value;
  });
}

// 使用示例
render('Hello, {{name}}!', { name: 'World' }); // "Hello, World!"
renderDeep('{{user.info.name}}', { user: { info: { name: 'Tom' } } }); // "Tom"

7. 数组按属性去重并排序

function uniqueAndSort(arr, key, sortKey, order = 'asc') {
  // 去重
  const map = new Map();
  arr.forEach(item => !map.has(item[key]) && map.set(item[key], item));
  
  // 排序
  return [...map.values()].sort((a, b) => {
    return order === 'asc' ? a[sortKey] - b[sortKey] : b[sortKey] - a[sortKey];
  });
}

// 示例
const users = [
  { id: 1, name: 'Tom', age: 20 },
  { id: 2, name: 'Jerry', age: 18 },
  { id: 1, name: 'Tom2', age: 25 }
];
uniqueAndSort(users, 'id', 'age'); // 按id去重按age升序排序