使用带有 for 循环更改数据的 switch 语句检索 [英] Using a switch statement with a for loop change data retrieved

查看:69
本文介绍了使用带有 for 循环更改数据的 switch 语句检索的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用具有不同列中的数据的文件进行处理.我想通过每个开关更改为每列提取的数据.我有一个值切换设置为我的变量,因此单击时值会更改.0-2.目前我可以运行切换,但值不会改变.下面是我当前的 switch 语句.有关完整代码和相关文件,请参阅链接

I am using processing with a file that has data in different columns. I am wanting to change the data being pulled for each column with each switch. I have a value toggle set as my variable so the value changes when clicked. 0-2. Currently I am able to run toggle, but the values do not change. Below is the current switch statement I have. For full code and associated files see Link

     PImage mapImage;
Table locationTable;
int rowCount;
Table dataTable;
float dataMin = MAX_FLOAT;
float dataMax = MIN_FLOAT;
int toggle = 0;
int x1;
int y1;
int x2;
int y2;

void setup() {
  size(750, 600);
  smooth();
  noStroke();

  mapImage = loadImage("map.png");
  x1 = 40;
  y1 = 40;

  x2 = width - 200;
  y2 = height - 80;
  locationTable = new Table("locations.tsv");
  rowCount = locationTable.getRowCount( );
  dataTable = new Table("povertynoheader.tsv");
  switch ( toggle ) {
    case 0:
    for (int row = 0; row < rowCount; row++) {
      float value = dataTable.getFloat(row, 1);
      if (value > dataMax) {
        dataMax = value;
    }
      if (value < dataMin) {
        dataMin = value;
      }
      break;
    }
        case 1:
    for (int row = 1; row < rowCount; row++) {
      float value = dataTable.getFloat(row, 0);
      if (value > dataMax) {
        dataMax = value;
    }
      if (value < dataMin) {
        dataMin = value;
      }

    }
            case 2:
    for (int row = 1; row < rowCount; row++) {
      float value = dataTable.getFloat(row, 3);
      if (value > dataMax) {
        dataMax = value;
    }
      if (value < dataMin) {
        dataMin = value;
      }  
    }
  }
  stateData = GetStateData();
}

void draw() {
  background(255);
  image(mapImage, 0, 0);
  surface.setResizable(true);

  DrawStats();
  AddTitle();
  drawLegend();
  drawsize();
}
void AddTitle() {
  fill(0);
  textSize(20);
  textAlign(CENTER);
  if ( toggle == 0 ) {
  text("2017 Poverty Rates (%) by State", width/2, 30);
  } else if (toggle == 1) {
    text("People in poverty by Household income in thousands ", width/2, 15); 
  }  else if (toggle == 2) {
      text("2014 Poverty Rates (%) by State ", width/2, 30);
  }
}

void drawLegend(){
  fill(0);
  textSize(10);
  textAlign(CENTER);
  if ( toggle == 0 ) {
  text("2017 Poverty Rates (Lowest to Highest)", 630, 300);
   int colorWidth = 15;
   int step = 1;
    noFill();  // make sure the rectangle and the points are not filled in  
    rectMode(CORNERS);
    rect(x1,y1,x2,y2);

   // Have 5 ranges of color values 
   noStroke();
   for ( int i = 1 ; i < 10 ; i = i + 2) {

        int legendX1 = x2 + step * colorWidth;
        int legendX2 = x2 + step * colorWidth + colorWidth;
        int legendY1 = (y1 + y2) / 2 - colorWidth / 2;
        int legendY2 = (y1 + y2) / 2 + colorWidth / 2;

        step = step + 1;
        float percent = norm(i, 1,10);
        color integratedColor = lerpColor(#03fc03,#fc0303,percent);
        fill(integratedColor);        
        rect(legendX1,legendY1,legendX2,legendY2);
     }   
   }
}

void DrawStats() {
  // draw circles
  for (StateData s : stateData) {
    fill(s.fill);
    ellipseMode(RADIUS);
    ellipse(s.location.x, s.location.y, s.radius, s.radius);
  }
  // draw text above circles
  for (StateData s : stateData) {
    if (dist(s.location.x, s.location.y, mouseX, mouseY) < s.radius+2) {
      fill(0);
      textAlign(CENTER);
      textSize(10);
      text(s.povertyRate + " (" + s.name + ")", s.location.x, s.location.y-s.radius-4);
    }
  }
}

void drawsize() {


void mousePressed() {

  if (toggle == 0 ) {
     toggle = 1; 
  } else if (toggle == 1) {
     toggle = 2;
  } else {
    toggle = 0;
  }

}
void keyPressed() {
  if ( key == ' ') {
    if (toggle == 0 ) {
      toggle = 1;
  } else if (toggle == 1) {
     toggle = 2;
  } else {
    toggle = 0;
  }
  }
}

推荐答案

我想首先说用户 @Dakshesh Garambha 是 100% 正确的.丢失的 break 可能是您的问题中最少的,所以它在您的工作中没有显示太多,但他成功地回答了您的问题,值得感谢.您可以在我的代码中看到一些关于如何编写 switch 语句的示例.好好看看.

I would like to start by saying that user @Dakshesh Garambha was 100% right. The missing break was probably the least of your problems, so it didn't show much on your work, but he answered your question successfully and deserve some thanks. You can see some examples of how to write a switch statement in my code. Take a good look.

好的,我刚刚打开了你的工作,还有很多重构工作要做​​.但是,勇气!所有这些都是非常可行的.

Ok, I just opened your work, and there's a lot of refactoring to work on. But, courage! All of this is very feasible.

首先,据我所知,您希望在几组数据之间toggle.没问题.你只需要相应地加载这些.您仍然需要存储它们,因此您必须修改 StateData 类.由于我很懒惰,我总是尝试以正确的方式编写代码,因此我建议为 GetStateData() 方法添加一个重载,而不是向 StateData 类添加各种细节我们可以拥有多组 StateData 并在运行中从一组切换到另一组.

First, As I understand this, you want to toggle between several sets of data. No problemo. You just have to load these accordingly. You still have to store them, so you'll have to modify the StateData class. As I'm very lazy, I always try to code stuff the right way, so instead of adding all sorts of details to the StateData class, I suggest to add an overload to the GetStateData() method so we can have several sets of StateData and switch from one to the other on the fly.

老实说,编码复杂的东西在大多数情况下都是错误的,所以让我们避免这一点.

Honestly, coding complicated stuff is a mistake most of the time, so let's avoir that.

GetStateData 签名现在看起来像这样:

GetStateData signature would now look like this:

ArrayList<StateData> GetStateData(int valueColumnNumber)

此处的数字只是 povertynoheader 文件中的列,用于获取要显示的值.问题是,我们无法计算贫困 2017 年家庭数量之类的半径.全局变量 dataMindataMax 变得毫无用处.擦除它们.我们将为每个数据集分别计算它们.

The number here is just the column in the povertynoheader file where to get the value you want to show. Thing is, we can't calculate the radius with poverty2017 for the number of households or stuff like that. The global variables dataMin and dataMax are becoming useless. Erase them. We'll calculate them for every data set separately.

如果你一直关注我,你的 StateData.pde 文件应该是这样的:

If you follow me so far, your StateData.pde file should look like like this:

class StateData {
  public String name;
  public PVector location;
  public float value;
  public float radius;
  public color fill;

  StateData(String name, PVector location, float value, float dataMin, float dataMax) {
    this.name = name;
    this.location = location;
    this.value = value;
    this.radius = map(value, 0, dataMax, 1.5, 15);

    float colorOffset = 255 * ((value - dataMin) / (dataMax - dataMin));
    this.fill = color(colorOffset, 255-colorOffset, 0);
  }
}

// Notice how we'll just use more StateData instead of making StateData more complex:
ArrayList<StateData> poverty2017;
ArrayList<StateData> povertyHouseholds;
ArrayList<StateData> poverty2014;

ArrayList<StateData> GetStateData(int valueColumnNumber) {
  ArrayList<StateData> data = new ArrayList<StateData>();

  // Since we need to know dataMin and dataMax, we'll just calculate one pair of these per data set
  float dataMin = MAX_FLOAT;
  float dataMax = MIN_FLOAT;
  for (int row = 0; row < rowCount; row++) {
    float value = dataTable.getFloat(row, valueColumnNumber);
    if (value > dataMax) {
      dataMax = value;
    }
    if (value < dataMin) {
      dataMin = value;
    }
  }

  for (int row = 0; row < rowCount; row++) {
    String abbrev = dataTable.getRowName(row);
    float value = dataTable.getFloat(abbrev, valueColumnNumber);
    float x = locationTable.getFloat(abbrev, 1);
    float y = locationTable.getFloat(abbrev, 2);
    data.add(new StateData(abbrev, new PVector(x, y), value, dataMin, dataMax));
  }

  return data;
}

为了填充这些数组,我们将在 setup() 方法中调用 GetStateData.这里的想法是在其他任何事情运行之前只计算一次所有这些东西,所以我们以后不用担心它:

To fill those arrays, we'll call GetStateData in the setup() method. The idea here is to calculate all this stuff only once, before anything else run, so we don't bother with it later:

void setup() {
  size(750, 600);
  smooth();
  noStroke();

  mapImage = loadImage("map.png");
  x1 = 40;
  y1 = 40;
  x2 = width - 200;
  y2 = height - 80;
  locationTable = new Table("locations.tsv");
  rowCount = locationTable.getRowCount( );
  dataTable = new Table("povertynoheader.tsv");

  // notice that we're not calculating dataMin and dataMax here anymore, as we erased these globals

  poverty2017 = GetStateData(1); // column #1
  povertyHouseholds = GetStateData(2); // column #2
  poverty2014 = GetStateData(3); // column #3... I guess?
}

当然,您必须修改 DrawStats() 方法,以便它绘制正确的数据.我建议您创建一个本地空数组列表,并使用`switch; 从正确的数据集填充它;声明:

And, of course, you have to modify the DrawStats() method so it draws the right data. I suggest you create a local empty arraylist and fill it from the right data set using a `switch; statement:

void DrawStats() {
  ArrayList<StateData> stateData = null;

  switch (toggle) {
    case 0:
      stateData = poverty2017;
      break;
    case 1:
      stateData = povertyHouseholds;
      break;
    case 2:
      stateData = poverty2014;
      break;
  }

  // nothing changed here: we're just drawing from a different source
  for (StateData s : stateData) {
    fill(s.fill);
    ellipseMode(RADIUS);
    ellipse(s.location.x, s.location.y, s.radius, s.radius);
  }
  // draw text (here so it's over the circles)
  for (StateData s : stateData) {
    if (dist(s.location.x, s.location.y, mouseX, mouseY) < s.radius+2) {
      fill(0);
      textAlign(CENTER);
      textSize(10);
      text(s.value + " (" + s.name + ")", s.location.x, s.location.y-s.radius-4);
    }
  }
}

就这样吧!每次点击或按空格键都会有不同的数据!

And here you go! Different data every time you click or press the spacebar!

现在,一些吹毛求疵:

AddTitle() 触发了我.我建议您使用与 DrawStats() 方法类似的技术重写它:

The AddTitle() triggers me. I suggest you rewrite it using a similar technique to the DrawStats() method:

void AddTitle() {
  fill(0);
  textSize(20);
  textAlign(CENTER);

  String title = "";
  switch (toggle) {
    case 0:
      title = "2017 Poverty Rates (%) by State";
      break;
    case 1:
      title = "People in poverty by Household income in thousands";
      break;
    case 2:
      title = "2014 Poverty Rates (%) by State";
      break;
  }
  text(title, width/2, 15);
}

我改变了什么?重要的部分不是开关,而是我使用变量 title 来避免多次编写 text(title, width/2, 15); .这样,如果您更改标题的高度,您就不必寻找并更改代码中使用此高度的每个地方.只有一个地方可以改变.我不会重新编写 drawLegend() 方法,但是你在做的时候应该记住我刚才说的;以后修复、改进或更改代码会更容易.(如果您想知道,这称为编写 DRY 代码 - 不要重复自己.每次复制和粘贴一行时,如果您想对其中的一个副本进行更改,则必须对其进行搜索,因此每个是一个潜在的未来错误.)

What did I change? The important part is not the switch, it's that I'm using a variable title to avoid writing the text(title, width/2, 15); several times. This way, if you change the height of the title, you don't have to hunt down and change every place in the code where you use this height. There's only one place to change. I wont re-write the drawLegend() method, but you should keep what I just said in mind when you do; it'll be easier to fix, improve or change your code later. (If you want to know, this is called writing DRY code - for Dont Repeat Yourself. Every time you copy and paste a line, you have to hunt it down if you ever want to make a change to one of it's copies, so each is a potential future bug.)

同样适用于 mouseClicked() - 而不是 mousePressed(),它们不一样 - 和 keyPressed:它们基本上是一个复制和粘贴.相反,创建一个将代码集中在一个地方的方法:

Same goes for mouseClicked() - and not mousePressed(), they are not the same - and keyPressed: they are basically a copy and paste. Instead, create a method which will centralize the code in only one place:

void mouseClicked() {
  IncreaseToggle();
}

void keyPressed() {
  if ( key == ' ') { IncreaseToggle(); }
}

void IncreaseToggle() {
  toggle++;
  if (toggle>2) {toggle=0;}
}

另外:我在 povertynoheader 文件中的一些数据中看到了逗号.它可能会给您带来问题,因为它不会轻易转换为浮点数.如果您发现缺失值,请先检查它们是否与这些行相对应.

Also: I've seen comma in some of your data in the povertynoheader file. It'll probably cause you problems, as it won't translate to float numbers easily. If you notice missing values, check first if they correspond to these lines.

希望所有这些都有帮助.玩得开心!

Hope all this helped. Have fun!

这篇关于使用带有 for 循环更改数据的 switch 语句检索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆