从Javascript中的对象返回最大数字和关联名称

从Javascript中的对象返回最大数字和关联名称,javascript,reactjs,Javascript,Reactjs,这是我的react应用程序- 我试图返回最高和最低纬度以及城市名称。我有它的工作,以返回纬度,但名称来了未定义。。。这很奇怪,因为在我的玩笑测试中,我的函数工作得很好。我正在使用React、Javascript和API加载和存储数据。。。我在这个函数中所做的是将所有纬度放入一个数组,然后执行Math.max,然后循环通过this.cities,查看对象中的哪个纬度与我们放入mostNorthLat的最高纬度匹配,然后获得与lat匹配的城市名称 这是带有纯函数的javascript文件: //Lo

这是我的react应用程序-

我试图返回最高和最低纬度以及城市名称。我有它的工作,以返回纬度,但名称来了未定义。。。这很奇怪,因为在我的玩笑测试中,我的函数工作得很好。我正在使用React、Javascript和API加载和存储数据。。。我在这个函数中所做的是将所有纬度放入一个数组,然后执行Math.max,然后循环通过this.cities,查看对象中的哪个纬度与我们放入mostNorthLat的最高纬度匹配,然后获得与lat匹配的城市名称

这是带有纯函数的javascript文件:

//Loads cities in API and injects it into this.cities

    async loadCities() {
            const data = await postData(url + "all");
            //Create a dictionary of cities and keep track of the last key
            const cities = {};
            data.forEach(x => {
                cities[x.key] = x;
                this.lastKey = (x.key > this.lastKey) ? x.key : this.lastKey;
            });

            this.cities = cities;
        }

//This is my add function I use for adding new cities to my API, which then React uses to create my cards for each object in my cities object in the API

    async addOrUpdate(city) {
            let theUrl;

            if (city.key) {
                theUrl = url + 'update'
            } else {
                theUrl = url + 'add'
                this.lastKey++;
                city.key = this.lastKey;
                city.population = Number(city.population)
            }
            await postData(theUrl, city);
            this.cities[city.key] = city;
    }

//My functions that are running the most North and most South

    getMostNorthern() {
            let latitudeArray = []
            let theName;
            for (let key in this.cities) {
                latitudeArray.push(this.cities[key].latitude)
            }
            let mostNorthLat = Math.max.apply(null, latitudeArray);
            for (let key in this.cities) {
                if (mostNorthLat === this.cities[key].latitude) {
                    theName = this.cities[key].name
                }
            }
            if (this.length() > 0) {
                return `${theName} at ${mostNorthLat}°`
            }
        }

    getMostSouthern() {
            let latitudeArray = []
            let theName;
            for (let key in this.cities) {
                latitudeArray.push(this.cities[key].latitude)
            }
            let mostSouthLat = Math.min.apply(null, latitudeArray);
            for (let key in this.cities) {
                if (mostSouthLat === this.cities[key].latitude) {
                    theName = this.cities[key].name
                }
            }
            if (this.length() > 0) {
                return `${theName} at ${mostSouthLat}°`
            }
        }
以下是城市对象的外观:

    {
        "key": 1, 
        "latitude": "1", 
        "longitude": "1", 
        "name": "City", 
        "population": 49500
    }, 
每个城市对象都保存在一个称为“城市”的主要对象中

    constructor() {
            this.cities = {};
            this.lastKey = 0;
        }
这是一个物体内部3个城市的样子:

    {
            '1': City {
              name: "Gangster's Paradise",
              latitude: -15,
              longitude: 5,
              population: 10,
              key: 1
            },
            '2': City {
              name: 'Pho City',
              latitude: 5,
              longitude: 52,
              population: 1050,
              key: 2
            },
            '3': City {
              name: 'Frisbee Land',
              latitude: 0,
              longitude: 12,
              population: 1000000,
              key: 3
            }
    }
我的反应部分:

    function CitiesApp() {
       const classes = useStyles();
       const [message, setMessage] = useState('')

       const [count, setCount] = useState(0)

       const [total, setTotal] = useState()
       const [northest, setNorthest] = useState()
       const [southest, setSouthest] = useState()

       useEffect(() => {
          //Load cities from the API - re-render when count is updated
          async function fetchData() {
             try {
                await cityCtrl.loadCities()
                updateSummary()
             } catch (e) {
                userMsg('Turn on the server')
             }
          }
          fetchData();
       }, [count]);

       async function onSave(city) {
          await cityCtrl.addOrUpdate(city)
          setCount(count + 1)
          updateSummary()
       }

       async function deleteCard(thekey) {
          await cityCtrl.deleteCard(thekey)
          setCount(count + 1)
          updateSummary()
       }

       async function moveIn(thekey, num) {
          await cityCtrl.movedIn(thekey, num)
          setCount(count + 1)
          updateSummary()
       }

       async function moveOut(thekey, num) {
          await cityCtrl.movedOut(thekey, num)
          setCount(count + 1)
          updateSummary()
       }

       function updateSummary() {
          setTotal(cityCtrl.getTotalPopulation())
          setNorthest(cityCtrl.getMostNorthern())
          setSouthest(cityCtrl.getMostSouthern())
       }
    }

我认为你可以通过
将所有工作放在一个循环中简化。cities

getMostNorthern() {
  if (!this.cities.length) return '';
  let mostNorthernCity;
  for (const key in this.cities) {
    if (!mostNorthernCity) {
      mostNorthernCity = this.cities[key];
      continue;
    }
    if (this.cities[key].latitude > mostNorthernCity.latitude) {
      mostNorthernCity = this.cities[key];
    }
  }
  return `${mostNorthernCity.name} at ${mostNorthernCity.latitude}`;
}

getMostSouthern
的工作方式相同,但您可以将变量重命名为
mostSouthernCity
,并使用小于比较器。

我发现了问题!我的设置方式是在react中使用defaultValue,最初,任何新城市都有默认的“”空白值。然后在我提交表单后更改。。。然而,如果我输入一个数字,它将只是在字符串中,因此我必须将经度和纬度转换为一个数字,就像我对人口所做的那样,然后我的函数工作

    async addOrUpdate(city) {
        let theUrl;

        if (city.key) {
            theUrl = url + 'update'
        } else {
            theUrl = url + 'add'
            this.lastKey++;
            city.key = this.lastKey;
            city.population = Number(city.population)
            city.latitude = Number(city.latitude)
            city.longitude = Number(city.longitude)
        }
        await postData(theUrl, city);
        this.cities[city.key] = city;
    }

看来你找到答案了

这里有一种通过对值数组排序来查找最大值和最小值的替代方法

这种方法使用具有规则对象的函数方法,而不是具有类的面向对象方法。请注意,这需要对代码进行重构,因为您当前使用的是
City
对象实例

const cities={
'1': {
名字:“黑帮的天堂”,
纬度:-15,
经度:5度,
人口:10,
关键词:1
},
'2': {
名称:'凤凰城',
纬度:5,
经度:52,
人口:1050,
关键词:2
},
'3': {
名称:“飞盘之地”,
纬度:0,
经度:12,
人口:1000000,
关键词:3
}
}
//城市对象包含的静态定义关键点
常数cityKeys=[
“姓名”,
“纬度”,
“经度”,
"人口",,
“钥匙”
]
//将值数组转换回城市对象
const cityArrayToObject=(城市)=>城市。
减少(
(累加器、电流、电流索引)=>{
累加器[cityKeys[currentIndex]]=当前
回流蓄能器
}, {}
)
//按从最小到最大的纬度对阵列排序
//然后返回转换后的第一个和最后一个元素
//使用上面的函数返回到一个对象。
//城市的值数组在排序之前如下所示:
/*
[
[“匪徒天堂”,-15,5,10,1],
[“飞盘地”,0,12,1000000,3],
[‘凤凰城’,5、52、1050、2]
]
*/
const sortedCities=对象
//用城市的钥匙做一个阵列
.钥匙(城市)
//将该数组映射到每个键的新值数组
.map((值,索引)=>Object.values(城市[value]))
//然后按索引1中的纬度对数组进行排序
.sort((a,b)=>a[1]-b[1])
//取出最后一个项目(pop),它是最大的
const max=cityarytoobject(sortedCities.pop())
//取出最低的第一项(班次)
const minimate=cityarytoobject(sortedCities.shift())
log('最大:',最大,'最小:',最小)
哪些产出:

Largest: {
  name: 'Pho City',
  latitude: 5,
  longitude: 52,
  population: 1050,
  key: 2
} 
Smallest: {
  name: "Gangster's Paradise",
  latitude: -15,
  longitude: 5,
  population: 10,
  key: 1
}

请注意,这并不能解释两个城市可能具有相同纬度的情况。

这两个城市是什么样子?@awarrier99我更新了问题以显示这一点。城市,谢谢!你能把整个课程和其他相关的文件都包括进去吗?建立一个基本的复制和测试它似乎工作fine@awarrier99当然,我已经添加了我的异步函数谢谢!这看起来更干净,也有效。你能解释一下continue在这个函数中的作用吗?我以前从未用过它
continue
将跳过
for
循环中的其余代码-因为我们不想将第一个城市与其自身进行比较,
continue
将在
this.cities
中跳过前面的下一个城市。非常感谢您在这方面对我进行深入的讨论,这真是太棒了!