Я пытаюсь найти надежный способ группировки элементов, чтобы значение было следующим в списке.
Данные у меня такие
let values = [
ChartDataEntry(x: 0.0, y: -13.0),
ChartDataEntry(x: 1.0, y: -13.0),
ChartDataEntry(x: 2.0, y: 0.68),
ChartDataEntry(x: 3.0, y: -13.0),
ChartDataEntry(x: 4.0, y: 1.7),
ChartDataEntry(x: 5.0, y: 0.5),
ChartDataEntry(x: 6.0, y: 10.0)
]
Я пытаюсь сгруппировать это, чтобы это было больше похоже на это
let values = [
[
ChartDataEntry(x: 0.0, y: -13.0),
ChartDataEntry(x: 1.0, y: -13.0),
ChartDataEntry(x: 3.0, y: -13.0)
],
[
ChartDataEntry(x: 2.0, y: 0.68)
],
[
ChartDataEntry(x: 4.0, y: 1.7),
ChartDataEntry(x: 5.0, y: 0.5),
ChartDataEntry(x: 6.0, y: -10.0)
]
]
По сути, группировка, которую я пытаюсь достичь, состоит в том, что элементы x со значением выше -13,0 идут вместе, а элементы ниже -13 идут вместе. Сложная часть — группировка по значению x.
Цель состоит в том, чтобы сгруппировать значения по значению x, которые находятся рядом друг с другом.
x: 2,0 находится рядом с 3,0, но это -13, поэтому он не принадлежит к одной группе, но если вы посмотрите на 4,0, 5,0 и 6,0, все они будут сгруппированы вместе, поскольку они имеют значение больше -13 последовательно
Я надеюсь это имеет смысл.
Почему -13? Вы пытаетесь сгруппировать точки на графике, которые очень близки? В этом случае -13 изменится в зависимости от значений других точек на графике, верно? Возможно, вам придется использовать какой-то другой алгоритм для достижения этой группировки. Боюсь, в таком случае все будет не так просто, как вы думаете.
Я нашел простое решение для достижения этой цели с помощью функции уменьшения. Если у кого-то есть другие более чистые, более краткие подходы, я весь внимание.
let grouped = values.filter({ $0.y != -13 }).reduce([[ChartDataEntry]]()) { result, item in
var result = result
if let lastX = result.last?.last?.x, item.x - 1.0 == lastX {
let lastIndex = result.count - 1
result[lastIndex].append(item)
} else {
result.append([item])
}
return result
}
Используйте метод уменьшить (в:_:) и перечислите элементы массива. Если значение ChartDataEntry y
меньше -13.0
, получите индекс массива, в котором его элементы меньше или равны -13.0
, и добавьте объект ChartDataEntry
к этому подмассиву. Если нет, найдите подмассив, который содержит объект ChartDataEntry
со значением x
, смежным с текущим объектом ChartDataEntry
, и добавьте к подмассиву. Если оба условия не выполняются, добавьте новый подмассив с объектом ChartDataEntry
.
let result = values.reduce(into: [[ChartDataEntry]]()) { (result, chart) in
if chart.y <= -13.0, let index = result.firstIndex(where: { $0.contains(where: { $0.y <= -13.0 }) }) {
result[index].append(chart)
} else if let index = result.firstIndex(where: { $0.contains(where: { $0.y > -13.0 && $0.x.advanced(by: 1) == chart.x }) }) {
result[index].append(chart)
} else {
result.append([chart])
}
}
print(result)
//[[ChartDataEntry(x: 0.0, y: -13.0), ChartDataEntry(x: 1.0, y: -13.0), ChartDataEntry(x: 3.0, y: -13.0)],
//[ChartDataEntry(x: 2.0, y: 0.68)],
//[ChartDataEntry(x: 4.0, y: 1.7), ChartDataEntry(x: 5.0, y: 0.5), ChartDataEntry(x: 6.0, y: 10.0)]]
Если я правильно понимаю, это простая композиция из трех отдельных процессов. 1) Разделите все элементы, находящиеся под или над
-13.0
. 2) Отсортируйте обе стороны по их значениям X. 3) Разделите элементы, чтобы сформировать ряды последовательных значений X. Я правильно понимаю?