Learn Courses My Dashboard

How to use .dat file in Xcode, swift 5.3

Hi ! i have a little bit experience like developer iOS, i need to know how to use a .dat file in swift, i need to decode this file and work with this data.
Can someone help me? i will thank you so much.

Bye

What is the format of the .dat file?

Are you planning on running this on the command line?

1 Like

I don’t Know the format. I put this file in Xcode and i can see the data, this file contain strings.
The data within the file, is like an excel spreadsheet.
But i don’t know how to call ( decode, transform) this file. I don’t know how to use this information.
Can you help me?

Can you paste in an example of the contents of the file. That way you can get some advice on the best way to handle it.

1 Like

Hi Chris, yes of course. I put it in Xcode and i can see this information:

This .dat file have this information.
Thanks very much for any information.

Bye

@Martinn

Is this .dat file available on a web site and it is updated on a regular basis?

Can you copy and paste the contents of the file in a reply as text. That way I can come up with an answer of how to process it.

Place 3 back-ticks ``` on the line above the data and 3 back-ticks ``` on the line below the data so that it is formatted nicely. The back-tick character is located on the same keyboard key as the tilde character ~.

2 Likes

Good morning ! thank you very much for your attention.
In answer to first question, this .dat file is an example of a challenge that i found in internet.
I think that this file is obtained from some base, but i don’t know.

In this challenge I must design a code that returns the team with the smallest difference between the column F and A as an answer.
But, my problems is i don’t know how to manager this file.
The exercise must be carried out with the aim of being able to reuse the code in whole or in part.

      Team            P     W    L   D    F      A     Pts
    1. Arsenal         38    26   9   3    79  -  36    87
    2. Liverpool       38    24   8   6    67  -  30    80
    3. Manchester_U    38    24   5   9    87  -  45    77
    4. Newcastle       38    21   8   9    74  -  52    71
    5. Leeds           38    18  12   8    53  -  37    66
    6. Chelsea         38    17  13   8    66  -  38    64
    7. West_Ham        38    15   8  15    48  -  57    53
    8. Aston_Villa     38    12  14  12    46  -  47    50
    9. Tottenham       38    14   8  16    49  -  53    50
   10. Blackburn       38    12  10  16    55  -  51    46
   11. Southampton     38    12   9  17    46  -  54    45
   12. Middlesbrough   38    12   9  17    35  -  47    45
   13. Fulham          38    10  14  14    36  -  44    44
   14. Charlton        38    10  14  14    38  -  49    44
   15. Everton         38    11  10  17    45  -  57    43
   16. Bolton          38     9  13  16    44  -  62    40
   17. Sunderland      38    10  10  18    29  -  51    40
   -------------------------------------------------------
   18. Ipswich         38     9   9  20    41  -  64    36
   19. Derby           38     8   6  24    33  -  63    30
   20. Leicester       38     5  13  20    30  -  64    28

Thank you agains for help me.
have a nice day !

Getting close to extracting the data into an array. It’s late here now so I will tackle it tomorrow morning.

1 Like

@Martinn

OK I have got the data out of the file and into an array so that it can be used in whatever way you need to.

Are you coding this in Storyboard or in SwiftUI?

The main thing to keep in mind that my solution requires that the data file be in exactly the same format each time. In other words the column position of the data items must be the same each time. ie order, team, played, won, lost, drawn, goalsFor, goalsAgainst and points

I am trying to figure out a way of converting the data into comma separated items as part of the processing to cater for the case where the column positioning may differ but the assumption being that there are the same number of columns and the data in each column is in the same position.

1 Like

Hi Chris, i’m using Storydoard in this momento, but i studying SwiftUI with you in the begging challenge.

I thought that use array was a good idea, but i don’t know how to figure out it.
I think that the information is always in the same order, name of columns, etc…
I believe this is the correct way to make it.

Thank for you time anda attention.

@Martinn

Ah, you are confusing me with Chris Ching. We both have the same first name - Chris.

I treated this exercise as a bit of a challenge too and I have written the user interface in SwiftUI because it is much easier.

I went to the trouble of collecting all the team logos (which are all available on Wikipedia) and used them in the program too.

If you want to have a look at the code, it is available at this link:

1 Like

Excuse me for the confusing :rofl: ! As near your name say “Moderator” i believed that you was Chris Ching :grin:
I will look at the code, thank you very much for you time !

Well, I didn’t go all out like Chris and create an entire project (because I am too lazy! :wink:), but here’s a solution I worked up…

//below is a function for turning raw team data from your .dat file into an array
//  of TeamStats structs
//once you have this array, you can do whatever you like with it

//NOTE: this code assumes the data will always have the same columns,
//  though they don't have to be in the same order

struct TeamStats {
    var name: String = ""
    //I guessed at what the various column titles mean
    var numPlayed: Int = 0
    var numWins: Int = 0
    var numLosses: Int = 0
    var numDraws: Int = 0
    var numF: Int = 0  //I have no idea what F stands for
    var numA: Int = 0  //I have no idea what A stands for
    var points: Int = 0
    
    var difference: Int {
        numF - numA
    }
}

extension Array where Element == TeamStats {
    var topRanked: TeamStats? {
        self.max { $0.points < $1.points }
    }
    
    var bottomRanked: TeamStats? {
        self.min { $0.points < $1.points }
    }
}

func convertRawDataToStats(_ rawData: String) -> [TeamStats] {
    //these are characters we don't care about during our scanning
    var skippableCharacters = CharacterSet.whitespacesAndNewlines
    skippableCharacters.insert(".")
    //we could also skip - characters, but that would cause a problem
    //  if we ever have a team name with a - in it
    //skippableCharacters.insert("-")
    
    //get our data
    var teamData = rawData
    
    //clean up the data
    
    //change multiple spaces to tabs
    //this will make it easy to split into columns
    teamData = teamData.replacingOccurrences(of: " {2,}",
                                             with: "\t",
                                             options: .regularExpression)
    //get rid of the weird \t-\t between columns "F" and "A"
    teamData = teamData.replacingOccurrences(of: "\t-\t",
                                             with: "\t",
                                             options: .regularExpression)

    //get rid of leading spaces and the divider line
    let mString = NSMutableString(string: teamData)
    let regex = try! NSRegularExpression(pattern: #"^\s+(?:-+\n)?"#,
                                         options: .anchorsMatchLines)
    regex.replaceMatches(in: mString,
                         options: [],
                         range: NSRange(location: 0, length: mString.length),
                         withTemplate: "")
    teamData = String(mString)
    
    //split into lines
    var lines = teamData.components(separatedBy: .newlines)
    //get header line and turn into column titles
    let columns = lines.removeFirst().components(separatedBy: "\t")
    
    
    //create an empty array of TeamStats structs
    var stats = [TeamStats]()
    
    for line in lines {
        let scanner = Scanner(string: line)
        scanner.charactersToBeSkipped = skippableCharacters
        
        var stat = TeamStats()
        //we don't care about the index
        _ = scanner.scanInt() ?? 0
        
        for col in columns {
            switch col {
            case "Team":
                //after we find the team name, we want to replace _ characters
                //  to convert things like "Aston_Villa" to "Aston Villa"
                stat.name = scanner.scanUpToCharacters(from: skippableCharacters)?
                                   .replacingOccurrences(of: "_", with: " ") ?? ""
            case "P":
                stat.numPlayed = scanner.scanInt() ?? 0
            case "W":
                stat.numWins = scanner.scanInt() ?? 0
            case "L":
                stat.numLosses = scanner.scanInt() ?? 0
            case "D":
                stat.numDraws = scanner.scanInt() ?? 0
            case "F":
                stat.numF = scanner.scanInt() ?? 0
            case "A":
                stat.numA = scanner.scanInt() ?? 0
            case "Pts":
                stat.points = scanner.scanInt() ?? 0
            default:
                //there are other ways this could be handled other than
                //  crashing
                //for instance, we could make stat a TeamStat? and set it
                //  to nil here; that would require some other changes
                //  as well
                fatalError("unknown column \(col)")
            }
        }
        
        stats.append(stat)
    }
    
    return stats
}

//get the raw data however you want
//  e.g., reading it in from your bundle or downloading it from
//  an API call or whatever

//then...
let teams = convertRawDataToStats(rawData)
print(teams.map { "\($0.name) difference = \($0.difference)" })

if let smallestDiff = teams.min(by: { abs($0.difference) < abs($1.difference) }) {
    print("smallest difference is \(smallestDiff.name) with \(smallestDiff.difference)")
}

if let topRanked = teams.topRanked {
    print("\(topRanked.name) is top ranked, with \(topRanked.points) points")
}

if let bottomRanked = teams.bottomRanked {
    print("\(bottomRanked.name) is bottom ranked, with \(bottomRanked.points) points")
}
2 Likes

Nice one Patrick.

Column F is goalsFor and column A is goalsAgainst. I assume that it relates to the overall competition where those goals are summed up. Makes sense since the higher order teams have more goalsFor.