           }
       end
       new_diff when is_map(new_diff) ->
-        new_value = Map.fetch!(list2, si)
+        new_value = list2 |> Map.fetch!(si)
         |> do_patch(new_diff)
         {list2, Map.put(new_list2, si, new_value), true}
       false ->

      {i, [value]} when is_map(value) ->
        neg_i = "_" <> i
        case Map.fetch(deleted_map, neg_i) do
          {:ok, [value2, 0, 0]} -> [{i, diff(value2, value)} | all_checked(tail, Map.delete(deleted_map, neg_i))]
          :error -> [head | all_checked(tail, deleted_map)]
        end
      _ -> [head | all_checked(tail, deleted_map)]
    end
  end

  defp check_map(list1) do
    case Enum.split_while(list1, &split_underscore/1) do
      {[], []} -> list1
      {_, []} -> list1
      {check, deleted} ->
        deleted_map = Enum.into(deleted, %{})
        all_checked(check, deleted_map)
    end
  end

  defp do_diff(l1, l2) when is_list(l1) and is_list(l2) do
    map1 = Enum.with_index(l1) |> Enum.into(%{})
    map2 = Enum.with_index(l2) |> Enum.into(%{})
    {rest_map2, new_list} = Enum.reduce(map1, {map2, %{}},
      fn({k, i1}, {new_map2, acc}) ->
        case Map.get(new_map2, k) do
          nil -> {new_map2, Map.put(acc, "_"<>to_string(i1), [k, 0, 0])}
          ^i1 -> {Map.delete(new_map2, k), acc}
          i2 -> {Map.delete(new_map2, k),
                 Map.put(acc, "_"<>to_string(i1), ["", i2, 3])}
        end
      end
    )
    Enum.reduce(rest_map2, new_list,
      fn({k2, i3}, acc) ->
        Map.put(acc, to_string(i3), [k2])
      end
    )
    |> Enum.to_list
    |> check_shift(0)
    |> check_map
    |> Enum.concat([{"_t", "a"}])
    |> Enum.into(%{})
  end

  end

  defp do_patch_list(list1, new_list1, diff1, i) do
    si = <<i+48>>
    {list2, new_list2, has_changed1, has_deleted1} =
      case Map.get(diff1, "_" <> si, false) do
        [_, 0, 0] -> {Map.delete(list1, si), new_list1, true, true}
        ["", new_i, 3] ->
          {
            list1,
            Map.put(new_list1, <<new_i+48>>, Map.get(list1, si)), true, false
          }
        false -> {list1, new_list1, false, false}
      end
