<commit_before>import getRandomValues from 'get-random-values'
import {
  IndexTuple,
  isIndexSegment,
  isIndexTuple,
  isKeySegment,
  KeyedSegment,
  Path,
  PathSegment
} from '@sanity/types'

const rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g
const reKeySegment = /_key\s*==\s*['"](.*)['"]/
const EMPTY_PATH: Path = []

export const FOCUS_TERMINATOR = '$'

export function get(obj: unknown, path: Path | string, defaultVal?: unknown): unknown {
  const select = typeof path === 'string' ? fromString(path) : path
  if (!Array.isArray(select)) {
    throw new Error('Path must be an array or a string')
  }

  let acc = obj
  for (let i = 0; i < select.length; i++) {
    const segment = select[i]
    if (isIndexSegment(segment)) {
      if (!Array.isArray(acc)) {
        return defaultVal
      }

      acc = acc[segment]
    }

    if (isKeySegment(segment)) {
      if (!Array.isArray(acc)) {
        return defaultVal
      }

      acc = acc.find(item => item._key === segment._key)
    }

    if (typeof segment === 'string') {
      acc = typeof acc === 'object' && acc !== null ? acc[segment] : undefined
    }

    if (typeof acc === 'undefined') {
      return defaultVal
    }
  }

  return acc
}

export function isEqual(path: Path, otherPath: Path): boolean {
  return (
    path.length === otherPath.length &&
    path.every((segment, i) => isSegmentEqual(segment, otherPath[i]))
  )
}

export function numEqualSegments(path: Path, otherPath: Path): number {
  return path.filter((segment, i) => isSegmentEqual(segment, otherPath[i])).length
}

export function isSegmentEqual(segmentA: PathSegment, segmentB: PathSegment): boolean {
  if (isKeySegment(segmentA) && isKeySegment(segmentB)) {
    return segmentA._key === segmentB._key
  }

  if (isIndexSegment(segmentA)) {
    return Number(segmentA) === Number(segmentB)
  }

  if (isIndexTuple(segmentA) && isIndexTuple(segmentB)) {
    return segmentA[0] === segmentB[0] && segmentA[1] === segmentB[1]
  }
<commit_msg>[util] Stop counting equal segments after first miss<commit_after>import getRandomValues from 'get-random-values'
import {
  IndexTuple,
  isIndexSegment,
  isIndexTuple,
  isKeySegment,
  KeyedSegment,
  Path,
  PathSegment
} from '@sanity/types'

const rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g
const reKeySegment = /_key\s*==\s*['"](.*)['"]/
const EMPTY_PATH: Path = []

export const FOCUS_TERMINATOR = '$'

export function get(obj: unknown, path: Path | string, defaultVal?: unknown): unknown {
  const select = typeof path === 'string' ? fromString(path) : path
  if (!Array.isArray(select)) {
    throw new Error('Path must be an array or a string')
  }

  let acc = obj
  for (let i = 0; i < select.length; i++) {
    const segment = select[i]
    if (isIndexSegment(segment)) {
      if (!Array.isArray(acc)) {
        return defaultVal
      }

      acc = acc[segment]
    }

    if (isKeySegment(segment)) {
      if (!Array.isArray(acc)) {
        return defaultVal
      }

      acc = acc.find(item => item._key === segment._key)
    }

    if (typeof segment === 'string') {
      acc = typeof acc === 'object' && acc !== null ? acc[segment] : undefined
    }

    if (typeof acc === 'undefined') {
      return defaultVal
    }
  }

  return acc
}

export function isEqual(path: Path, otherPath: Path): boolean {
  return (
    path.length === otherPath.length &&
    path.every((segment, i) => isSegmentEqual(segment, otherPath[i]))
  )
}

export function numEqualSegments(path: Path, otherPath: Path): number {
  const length = Math.min(path.length, otherPath.length)
  for (let i = 0; i < length; i++) {
    if (!isSegmentEqual(path[i], otherPath[i])) {
      return i
    }
  }
  return length
}

export function isSegmentEqual(segmentA: PathSegment, segmentB: PathSegment): boolean {
  if (isKeySegment(segmentA) && isKeySegment(segmentB)) {
    return segmentA._key === segmentB._key
  }

  if (isIndexSegment(segmentA)) {
    return Number(segmentA) === Number(segmentB)
  }

  if (isIndexTuple(segmentA) && isIndexTuple(segmentB)) {
    return segmentA[0] === segmentB[0] && segmentA[1] === segmentB[1]
  }

{'fraction_non_alphanumeric': 0.18188218727998123, 'fraction_numerical': 0.0035203003989673787, 'mean_word_length': 3.3847736625514404, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '352554', 'n_tokens_mistral': 1456, 'n_tokens_neox': 1423, 'n_words': 336}