Sitelet https://comparejson.com/blog/array-comparison-methods-in-practice/
Guides
JSON

JSON Array Comparison in Practice: By Index vs LCS vs Unordered

Oct 3, 2026 · 5 min read

The docs explain the three array comparison methods in a paragraph each. That’s enough to pick one — but not enough to predict what you’ll actually see when the diff comes back. This post runs the same data through all three methods and shows the exact output each produces, because the differences are bigger than the names suggest.

Quick recap of the mechanics (details in how the engine works):

  • By Index pairs a[i] with b[i] and recurses on each pair.
  • LCS computes the longest common subsequence of deep-equal elements via dynamic programming; anything outside it is an insertion or deletion.
  • Unordered treats the arrays as multisets: each base element consumes one deep-equal match on the contrast side.

Same option, three very different answers.

Scenario 1: one element inserted in the middle

An event log gains a single entry at position 1:

{ "items": [1, 2, 3, 4] }
{ "items": [1, 5, 2, 3, 4] }

By Index sees positional alignment shift and reports a cascade:

valueChanged  items[1]
valueChanged  items[2]
valueChanged  items[3]
added         items[4]

Four differences for one insertion — technically correct, practically useless. Everything after the insertion point “changed”.

LCS finds the common subsequence [1, 2, 3, 4] and reports exactly what happened:

added  items[1]

Unordered also nails this one — every base element finds a match, one contrast element is left over:

added  items[1]

Winner: LCS or Unordered. By Index is only honest here if position is genuinely meaningful.

Scenario 2: pure reordering

Same elements, different order:

{ "items": [1, 2, 3] }
{ "items": [3, 1, 2] }

By Index reports every position as changed:

valueChanged  items[0]
valueChanged  items[1]
valueChanged  items[2]

LCS keeps the longest ordered run it can ([1, 2]) and moves the rest:

deleted  items[2]
added    items[0]

Unordered says nothing at all:

(no differences)

Which answer is right depends entirely on your data. Reordered steps in a deployment pipeline? By Index’s alarm is correct — order is meaning. Reordered tags on a blog post? Unordered’s silence is correct. This is the scenario where picking the wrong method either floods you with noise or hides a real regression.

Scenario 3: an element modified in place

Here’s the trade-off the docs don’t spell out. An object’s field changes inside an array:

{ "users": [{ "id": 1, "role": "admin" }, { "id": 2, "role": "user" }] }
{ "users": [{ "id": 1, "role": "admin" }, { "id": 2, "role": "owner" }] }

By Index recurses into the pair and pinpoints the field:

valueChanged  users[1].role

LCS matches elements by deep equality — and { "id": 2, "role": "user" } is not deep-equal to { "id": 2, "role": "owner" }. So the element falls out of the subsequence entirely:

deleted  users[1]
added    users[1]

Unordered behaves the same way:

deleted  users[1]
added    users[1]

Same index, no hint about what inside changed. If your arrays contain objects and you care about field-level changes, LCS and Unordered lose information — they can’t say “role changed from user to owner”, only “something at [1] is gone, something new is at [1]”. By Index is the only method that preserves field-level precision.

Scenario 4: duplicates are counted, not ignored

Unordered is often described as “set comparison”, but the implementation is a multiset comparison: each match is consumed one-for-one.

{ "tags": [1, 2, 2, 3] }
{ "tags": [3, 1, 2] }

The two 2s on the left can only consume one 2 on the right:

deleted  tags[2]

If duplicates are significant in your data, this is exactly what you want. If you genuinely want set semantics (“same unique values”), you should deduplicate before comparing — or know that Unordered will flag count differences.

Performance: the hidden axis

The three methods also differ in cost, which matters on large arrays:

MethodTime complexityNotes
By IndexO(n) comparisonsPlus one recursive comparison per pair
LCSO(m × n) deep-equality checksEach DP cell may recursively compare two entire subtrees
UnorderedO(m × n) worst caseEvery unmatched base element scans the contrast side

For a hundred-element array you’ll never feel any of this. For a 10,000-element array of nested objects, LCS’s DP table — with a full recursive comparison in every cell — is genuinely expensive, and Unordered’s quadratic scan isn’t far behind. By Index scales linearly and is the only method that’s essentially free at any size.

Choosing with eyes open

Your array is…Best methodWhat you give up
Positional (tuples, time series, table rows)By IndexInsertions shift everything — noise on misaligned lists
Ordered, occasionally edited (logs, changelogs)LCSField-level precision on modified elements; O(m·n) cost
Orderless (tags, permissions, flags)UnorderedOrder changes are invisible; whole-element add/delete reporting

The one-line version: By Index is precise but brittle, LCS is minimal but shallow, Unordered is calm but blind to order.

Try it on your own arrays — the method switch lives in Settings, and you can flip it and re-run the comparison in seconds: compare two JSON files now.