0

I have a question I cannot figure out. Is there an easier way to separate an array into other arrays. In the code below I do a Trace route and filter out everything except the ping rates.

Then I break down that array into individual nodes. The only downside is if it only takes 2 hops then I get an error, "fatal error: Index out of range." because I have it set up to create 15 node arrays. I have also tried putting ..

let count = pingRate.count
if count < 15 {
aNodeArray += pingRate[14]
}

Is there an easier way? I wish there was a way to do a .count and then populate the Int the is required on each node.

let task = Process()
    task.launchPath = "/bin/sh"
    task.arguments = ["-c", "traceroute -nm 15 -q 1 8.8.8.8"]

    let pipe = Pipe()
    task.standardOutput = pipe
    task.launch()
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as! String
    var array = output.components(separatedBy: " ")

    array = array.filter({ $0.contains(".")})
    let pingRate: [[Double]] = array.enumerated().filter({ index, _ in
        index % 2 != 0
    }).map { [Double($0.1)!] }
    let aNode = pingRate[0]
    let bNode = pingRate[1]
    let cNode = pingRate[2]
    let dNode = pingRate[3]
    let eNode = pingRate[4]

    aNodeArray += aNode
    bNodeArray += bNode
    cNodeArray += cNode
    dNodeArray += dNode
    eNodeArray += eNode

Once I get that done then I sort and find the min, max, and average.

    let sorted = aNodeArray.sorted()
    let numbers = sorted
    print(numbers)
    let min = numbers[0]

    var sum = 0 as Double
    for number in numbers {
        sum += number
    }
    let mean = Double(sum) /
        Double (numbers.count)
    let x = mean
    let avg = round(1000.0 * x) / 1000.0
    let maxBR = numbers.last! as Double
    let max = round(1000.0 * maxBR) / 1000.0

    print(min)
    print(max)
    print(avg)

Edit

I did stumble upon chunks and stride from... Swift: what is the right way to split up a [String] resulting in a [[String]] with a given subarray size?

I am trying to figure a way to implement that for my needs

Edit

And looking at that code. Can anyone tell me why I get the Color spinning wheel until the process() is finished?

Community
  • 1
  • 1
JonnyTombstone
  • 219
  • 1
  • 2
  • 6

1 Answers1

0

I know that there are more efficient algorithms to calculate your ping rate statistics but the code below should do the job.

let task = Process()
task.launchPath = "/bin/sh"
task.arguments = ["-c", "traceroute -nm 15 -q 1 8.8.8.8"]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()

let data = pipe.fileHandleForReading.readDataToEndOfFile()
guard
  let pingRates = String(data: data, encoding: .utf8)?
    .components(separatedBy: " ")
    .filter({ $0.contains(".") })
    .flatMap({ Double($0) }),
  pingRates.count > 0
else {
  return
}
print("ping rate(min) = \(pingRates.min()!.rounded())")
print("ping rate(max) = \(pingRates.max()!.rounded())")
print("ping rate(avg) = \((pingRates.reduce(0, +) / Double(pingRates.count)).rounded())")

The trick to eliminating the IP addresses in your output is to let Double.init fail on them and then flatMap will remove those nil values.

Price Ringo
  • 3,424
  • 1
  • 19
  • 33