0

I have a service that is querying a backend API. The API returns a set of comma delimited lines of text. These columns correspond to the attributes in a TypeScript class that I've created. The class is:

export class TopTalker {
    constructor(
        public source: string,
        public protocol: number,
        public packets: number,
        public _percent: string,
        public _tally: string
    ) {}
}

I am currently building objects out of these like so:

  getTopTalkers() {
    this._silk.topTalkers().subscribe(
        data => {
        let results = <any>[];
        results = data;
        this.topTalkers = <any>[];
        for (let row of results) {
          let thisTalker = row.split(/,/);
          let a = new TopTalker(
            thisTalker[0],
            thisTalker[1],
            thisTalker[2],
            thisTalker[3],
            thisTalker[4]);
          if(thisTalker.length > 1){   // Was getting a blank line
            this.topTalkers.push(a);
          }
        }
      console.log(this.largestTransfers);
      },
        err => console.error(err),
        () => console.log('Processed talkers')
        );
  }

Here is an example of the data returned by the API:

["8.248.215.242,6,7037358,53.111350,53.111350","8.248.209.245,6,2459465,18.561725,71.673076","192.168.2.86,6,604136,4.559450,76.232525","192.168.2.43,6,295422,2.229567,78.462092","192.168.2.39,6,254746,1.922583,80.384675","8.248.211.241,6,182544,1.377670,81.762345","192.168.2.69,6,180162,1.359693,83.122038","8.250.125.246,6,152862,1.153658,84.275697","8.248.213.243,6,93544,0.705982,84.981679","167.206.10.209,6,69862,0.527253,85.508931",""]

This works, but it feels really wrong. Is there some feature of Angular or TypeScript that I am missing that would allow me to map each line to create an array of objects directly?

9
  • You want to turn the array of comma-seperated strings into an array of TopTalkers, correct? Commented Dec 27, 2017 at 19:55
  • You could move the transformation into it's own factory function that receives a row and returns a TopTalker for readability but that's pretty much it. Commented Dec 27, 2017 at 19:57
  • @toskv So other than modularizing it, there's really nothing more "automatic" that can be done? Commented Dec 27, 2017 at 20:01
  • nope, javascript can't transform an arbitrary string to an arbitrary object. :( Commented Dec 27, 2017 at 20:03
  • 1
    your code transforms an array of strings to an array of objects. I didn't consider the array as being a part of the problem. The problem is transforming a row into a Talker.. But maybe I got the problem wrong, if so please help me understand. :) Commented Dec 27, 2017 at 20:06

2 Answers 2

1

If I understand your code correctly, something like this should be pretty close to what you're after (and is a lot easier to read, imo)

getTopTalkers() {
  this._silk.topTalkers().subscribe(
    results => {
      this.topTalkers = results.map((row, index, rows) => {
        let thisTalker = row.split(/,/);

        // Avoid blank lines by checking length
        if (thisTalker.length > 1) {
          new TopTalker(
            thisTalker[0],
            thisTalker[1],
            thisTalker[2],
            thisTalker[3],
            thisTalker[4]
          );
        }
      })
    },
    err => console.error(err),
    () => console.log('Processed talkers')
  );
}

Ideally, I'd explore getting that service updated to not return grotesque comma-separated strings.

Sign up to request clarification or add additional context in comments.

Comments

1

You could simplify your constructor signature a little bit by moving the mapping work into the body, like so:

class TopTalker {

    public source: string;
    public protocol: number;
    public packets: number;
    public _percent: string;
    public _tally: string;

    constructor(sourceRow: string[]) { 
        this.source = sourceRow[0];
        this.protocol = parseInt(sourceRow[1]);
        this.packets = parseInt(sourceRow[2]);
        this._percent = sourceRow[3];
        this._tally = sourceRow[4];
    }
}

Which would remove some of the complexity from the instantiating code:

for (let row of results) {
      let thisTalker = row.split(/,/);
      let a = new TopTalker(thisTalker);
      this.topTalkers.push(a);        
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.