最近是金三银四跳槽季,网上天天看到别人说:
- 江某某进了大公司
- 克某某进入了中公司
- 郎某某进入了小公司
那么什么是大公司,什么是小公司,到底是以什么作为依据来判断的,有没有什么标准呢?
有的, 国家统计局.
公司大小怎么判断?
要判断公司大小,首先要划分行业, 公司大小判断随着行业不同而变化, 每个行业都不同.
行业的划分, 是按照《国民经济行业分类》(GB/T 4754—2017)进行的.国标最近一次修订是2017年,因此统计局随之给出了相应统计标准的修改:《统计上大中小微型企业划分办法(2017)》 .
大型、中型和小型企业须同时满足所列指标的下限,否则下划一档;微型企业只须满足所列指标中的一项即可。
规则分析
这个表格, 按我粗浅的理解是这样的.
- 每个行业都有对应的指标
- 指标是根据3个数轴上的点划分的4个区间
- 附录里的注释1说明, 所有指标中评分最低的那个为准
举例说明,以餐饮业为例,分别考核从业人员和营业收入两个指标.
-
从业人员划分界限分别为: 10,100,2000,这里把数轴划为-∞,10),[10,100),[100,2000),[2000,+∞). -
营业收入, 划分界限分别为: 100,2000,10000 -
若一公司员工1人, 收入10001, 很明显,应该按照最低的人员这项定为
微型
(注, 这里可能理解的规则不对, 下划一档这词没搞明白,按照else if理解的而不是else)
数据整理
很明显, 我们这里需要的是把表格中的相关信息都整理出来,才能写代码.
这是个体力活,我已经整理过了.输出格式是以行业为key,规则列表为value的一个map结构,输出为JSON是这样的.
规则JSON
{"农、林、牧、渔业":[{"key":"Y","value":[50,500,20000]}],"工业":[{"key":"X","value":[20,300,1000]},{"key":"Y","value":[300,2000,40000]}],"建筑业":[{"key":"Y","value":[300,6000,80000]},{"key":"Z","value":[300,5000,80000]}],"批发业":[{"key":"X","value":[5,20,200]},{"key":"Y","value":[1000,5000,40000]}],"零售业":[{"key":"X","value":[10,50,300]},{"key":"Y","value":[100,500,20000]}],"交通运输业":[{"key":"X","value":[20,300,1000]},{"key":"Y","value":[200,3000,30000]}],"仓储业":[{"key":"X","value":[20,100,200]},{"key":"Y","value":[100,1000,30000]}],"邮政业":[{"key":"X","value":[20,300,1000]},{"key":"Y","value":[100,2000,30000]}],"住宿业":[{"key":"X","value":[10,100,300]},{"key":"Y","value":[100,2000,10000]}],"餐饮业":[{"key":"X","value":[10,100,300]},{"key":"Y","value":[100,2000,10000]}],"信息传输业":[{"key":"X","value":[10,100,2000]},{"key":"Y","value":[100,1000,100000]}],"软件和信息技术服务业":[{"key":"X","value":[10,100,300]},{"key":"Y","value":[50,1000,10000]}],"房地产开发经营":[{"key":"Y","value":[100,1000,200000]},{"key":"Z","value":[2000,5000,10000]}],"物业管理":[{"key":"X","value":[100,300,1000]},{"key":"Y","value":[500,1000,5000]}],"租赁和商务服务业":[{"key":"X","value":[10,100,300]},{"key":"Z","value":[100,8000,120000]}],"其他未列明行业":[{"key":"X","value":[10,100,300]}]}
附整理代码
static final String s = "农、林、牧、渔业 营业收入(Y) 万元 Y≥20000 500≤Y<20000 50≤Y<500 Y<50\n工业 * 从业人员(X) 人 X≥1000 300≤X<1000 20≤X<300 X<20\n 营业收入(Y) 万元 Y≥40000 2000≤Y<40000 300≤Y<2000 Y<300\n建筑业 营业收入(Y) 万元 Y≥80000 6000≤Y<80000 300≤Y<6000 Y<300\n 资产总额(Z) 万元 Z≥80000 5000≤Z<80000 300≤Z<5000 Z<300\n批发业 从业人员(X) 人 X≥200 20≤X<200 5≤X<20 X<5\n 营业收入(Y) 万元 Y≥40000 5000≤Y<40000 1000≤Y<5000 Y<1000\n零售业 从业人员(X) 人 X≥300 50≤X<300 10≤X<50 X<10\n 营业收入(Y) 万元 Y≥20000 500≤Y<20000 100≤Y<500 Y<100\n交通运输业 * 从业人员(X) 人 X≥1000 300≤X<1000 20≤X<300 X<20\n 营业收入(Y) 万元 Y≥30000 3000≤Y<30000 200≤Y<3000 Y<200\n仓储业 从业人员(X) 人 X≥200 100≤X<200 20≤X<100 X<20\n 营业收入(Y) 万元 Y≥30000 1000≤Y<30000 100≤Y<1000 Y<100\n邮政业 从业人员(X) 人 X≥1000 300≤X<1000 20≤X<300 X<20\n 营业收入(Y) 万元 Y≥30000 2000≤Y<30000 100≤Y<2000 Y<100\n住宿业 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10\n 营业收入(Y) 万元 Y≥10000 2000≤Y<10000 100≤Y<2000 Y<100\n餐饮业 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10\n 营业收入(Y) 万元 Y≥10000 2000≤Y<10000 100≤Y<2000 Y<100\n信息传输业 * 从业人员(X) 人 X≥2000 100≤X<2000 10≤X<100 X<10\n 营业收入(Y) 万元 Y≥100000 1000≤Y<100000 100≤Y<1000 Y<100\n软件和信息技术服务业 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10\n 营业收入(Y) 万元 Y≥10000 1000≤Y<10000 50≤Y<1000 Y<50\n房地产开发经营 营业收入(Y) 万元 Y≥200000 1000≤Y<200000 100≤Y<1000 Y<100\n 资产总额(Z) 万元 Z≥10000 5000≤Z<10000 2000≤Z<5000 Z<2000\n物业管理 从业人员(X) 人 X≥1000 300≤X<1000 100≤X<300 X<100\n 营业收入(Y) 万元 Y≥5000 1000≤Y<5000 500≤Y<1000 Y<500\n租赁和商务服务业 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10\n 资产总额(Z) 万元 Z≥120000 8000≤Z<120000 100≤Z<8000 Z<100\n其他未列明行业 * 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10";
final static LinkedMultiValueMap<String, Pair<String, List<Integer>>> map = new LinkedMultiValueMap<>();
String[] code = new String[1];
Arrays.stream(s.split("\\n")).forEach(line -> { if (!line.matches("^\\s+.*$")) { code[0] = line.split("\\s")[0]; line = line.substring(line.split("\\t")[0].length()); } map.add(code[0], Pair.of(line.substring(line.indexOf("(") + 1, line.indexOf("(") + 2), Arrays.stream(line.trim().split("\\t")).skip(3).map(x -> Integer.decode(x.substring(x.lastIndexOf("<") + 1).trim())).sorted().collect(Collectors.toList()))); });
System.out.println(JSON.toJSONString(map,true));
规则运算
有了规则当然是要用的, 这个表格里一共规定了3个指标:
- 从业人员(X)
- 营业收入(Y)
- 资产总额(Z)
因此可以设计如下方法:
String calc(String industry, Integer X, Integer Y, Integer Z);
3个指标都不是一定有值的, 所以这里可null,用包装类即可.
实现代码
这里做了个小逻辑
-
微型企业可以缺必须指标,其他的不可以会报错.
-
industry名称假定和表格里的一模一样,这个需要调用方自己保证或处理.
static final String[] type=new String[]{"微","小","中","大"};
public static String calc(String industry, Integer X, Integer Y, Integer Z) {
var rules = map.getOrDefault(industry,map.get("其他未列明行业"));
List<Integer> scores = new ArrayList<>(rules.size());
for (Pair<String, List<Integer>> rule : rules) {
Integer value=null;
String key = rule.getKey();
switch (key) {
case "X": value = X; break;
case "Y": value = Y; break;
case "Z": value = Z; break;
}
int level = value == null ? Integer.MAX_VALUE : locate(rule.getValue(), value);
scores.add(level);
}
Integer min = Collections.min(scores);
if(min!=0 && scores.contains(Integer.MAX_VALUE))throw new IllegalArgumentException();
return type[min];
}
区间判断代码
数字落在哪个区间, 这个逻辑写了一会比较, 后来发现是我想多了,没那么复杂.
这里只需要计算一个数字从左到右,超过了几个指标即可.比如使用餐饮业的[10,100,2000],从左到右逐个比较,
- 一个坎儿都过不去的是0,对应<10
- 过去1个坎过不了第二个的是1,对应[10,100)
- .....以此类推
理顺这个以后写成代码就简单了,就是一个简单的for循环
static int locate(List<Integer> pivotal, Integer x) {
int i = 0;
for (; i < pivotal.size(); i++) {
if (x < pivotal.get(i)) {
return i;
}
}
return i;
}
测试
public static void main(String[] args) {
Assert.assertEquals( "微",calc("工业", 19, 40000, null));
Assert.assertEquals( "小",(calc("工业", 20, 40000, null)));
Assert.assertEquals( "中",(calc("工业", 300, 40000, null)));
Assert.assertEquals( "大",(calc("工业", 1000, 40000, null)));
Assert.assertEquals( "微",calc("工业", 19, 2000, null));
Assert.assertEquals( "小",(calc("工业", 20, 2000, null)));
Assert.assertEquals( "中",(calc("工业", 300, 2000, null)));
Assert.assertEquals( "中",(calc("工业", 1000, 2000, null)));
Assert.assertEquals( "微",calc("工业", 19, 300, null));
Assert.assertEquals( "小",(calc("工业", 20, 300, null)));
Assert.assertEquals( "小",(calc("工业", 300, 300, null)));
Assert.assertEquals( "小",(calc("工业", 1000, 300, null)));
Assert.assertEquals( "微",calc("工业", 19, 200, null));
Assert.assertEquals( "微",(calc("工业", 20, 200, null)));
Assert.assertEquals( "微",(calc("工业", 300, 200, null)));
Assert.assertEquals( "微",(calc("工业", 1000, 200, null)));
}
简单用了工业试了下, 理论上没问题了. 没有进行详测
后话
好了. 今天的水文时间到此结束.
这主要是个洗数据的脏活儿, json洗出来以后就算结束了.后面我的实现只是一孔之见.
对于下调一档那块, 还没理解明白, 按照理解的方式,找最低级实现的.如果下调一档指的是, 一个指标是大,另一个指标是微,最高的那个往下调一档变成中的话, 代码可能需要写成这样,不太确定.
Integer max = Collections.max(scores);
if(scores.stream().anyMatch(x->!x.equals(max))){
return type[max-1];
}
暂时我还是按照取最小来处理.
附全代码
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.util.LinkedMultiValueMap;
import java.util.*;
import java.util.stream.Collectors;
public class CorpSize {
private static final String s = "农、林、牧、渔业 营业收入(Y) 万元 Y≥20000 500≤Y<20000 50≤Y<500 Y<50\n工业 * 从业人员(X) 人 X≥1000 300≤X<1000 20≤X<300 X<20\n 营业收入(Y) 万元 Y≥40000 2000≤Y<40000 300≤Y<2000 Y<300\n建筑业 营业收入(Y) 万元 Y≥80000 6000≤Y<80000 300≤Y<6000 Y<300\n 资产总额(Z) 万元 Z≥80000 5000≤Z<80000 300≤Z<5000 Z<300\n批发业 从业人员(X) 人 X≥200 20≤X<200 5≤X<20 X<5\n 营业收入(Y) 万元 Y≥40000 5000≤Y<40000 1000≤Y<5000 Y<1000\n零售业 从业人员(X) 人 X≥300 50≤X<300 10≤X<50 X<10\n 营业收入(Y) 万元 Y≥20000 500≤Y<20000 100≤Y<500 Y<100\n交通运输业 * 从业人员(X) 人 X≥1000 300≤X<1000 20≤X<300 X<20\n 营业收入(Y) 万元 Y≥30000 3000≤Y<30000 200≤Y<3000 Y<200\n仓储业 从业人员(X) 人 X≥200 100≤X<200 20≤X<100 X<20\n 营业收入(Y) 万元 Y≥30000 1000≤Y<30000 100≤Y<1000 Y<100\n邮政业 从业人员(X) 人 X≥1000 300≤X<1000 20≤X<300 X<20\n 营业收入(Y) 万元 Y≥30000 2000≤Y<30000 100≤Y<2000 Y<100\n住宿业 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10\n 营业收入(Y) 万元 Y≥10000 2000≤Y<10000 100≤Y<2000 Y<100\n餐饮业 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10\n 营业收入(Y) 万元 Y≥10000 2000≤Y<10000 100≤Y<2000 Y<100\n信息传输业 * 从业人员(X) 人 X≥2000 100≤X<2000 10≤X<100 X<10\n 营业收入(Y) 万元 Y≥100000 1000≤Y<100000 100≤Y<1000 Y<100\n软件和信息技术服务业 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10\n 营业收入(Y) 万元 Y≥10000 1000≤Y<10000 50≤Y<1000 Y<50\n房地产开发经营 营业收入(Y) 万元 Y≥200000 1000≤Y<200000 100≤Y<1000 Y<100\n 资产总额(Z) 万元 Z≥10000 5000≤Z<10000 2000≤Z<5000 Z<2000\n物业管理 从业人员(X) 人 X≥1000 300≤X<1000 100≤X<300 X<100\n 营业收入(Y) 万元 Y≥5000 1000≤Y<5000 500≤Y<1000 Y<500\n租赁和商务服务业 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10\n 资产总额(Z) 万元 Z≥120000 8000≤Z<120000 100≤Z<8000 Z<100\n其他未列明行业 * 从业人员(X) 人 X≥300 100≤X<300 10≤X<100 X<10";
private static final String[] type=new String[]{"微","小","中","大"};
private final static LinkedMultiValueMap<String, Pair<String, List<Integer>>> map = new LinkedMultiValueMap<>();
static {
String[] code = new String[1];
Arrays.stream(s.split("\\n")).forEach(line -> { if (!line.matches("^\\s+.*$")) { code[0] = line.split("\\s")[0]; line = line.substring(line.split("\\t")[0].length()); } map.add(code[0], Pair.of(line.substring(line.indexOf("(") + 1, line.indexOf("(") + 2), Arrays.stream(line.trim().split("\\t")).skip(3).map(x -> Integer.decode(x.substring(x.lastIndexOf("<") + 1).trim())).sorted().collect(Collectors.toList()))); });
}
public static String calc(String industry, Integer X, Integer Y, Integer Z) {
var rules = map.getOrDefault(industry,map.get("其他未列明行业"));
List<Integer> scores = new ArrayList<>(rules.size());
for (Pair<String, List<Integer>> rule : rules) {
Integer value=null;
String key = rule.getKey();
switch (key) {
case "X": value = X; break;
case "Y": value = Y; break;
case "Z": value = Z; break;
}
int level = value == null ? Integer.MAX_VALUE : locate(rule.getValue(), value);
scores.add(level);
}
Integer min = Collections.min(scores);
if(min!=0 && scores.contains(Integer.MAX_VALUE))throw new IllegalArgumentException();
return type[min];
}
static int locate(List<Integer> pivotal, Integer x) {
int i = 0;
for (; i < pivotal.size(); i++) {
if (x < pivotal.get(i)) {
return i;
}
}
return i;
}
}
这里还有很多遗留问题.
- 为了微信排版篇幅问题,故意用了很多1行风格的代码.
农、林、牧、渔业暂时是合并的key, 可以考虑拆开.- 行业名称精确匹配,容易导致匹配不到行业进入默认规则,这块可以自行处理.
有好事的朋友愿意接着改Java的话,可以接着拿去改,也可以直接拿整理好的json去用.授权协议和以前, 留言即可获得任意权.