英文:
How to print the sum of values from the same objects of 2 parameter in array
问题
public class Dollars
{
private String name;
private int dollars;
public Dollars(String name, int dollars)
{
this.name = name;
this.dollars = dollars;
}
public String getName()
{
return name;
}
public int getChange()
{
return dollars;
}
}
public class TestDollars
{
public static void displayArray(Dollars[] dol)
{
int sum = 0;
for (int n = 0; n < dol.length; n++)
{
sum = dol[n].getChange();
for (int m = n + 1; m < dol.length; m++)
{
if (dol[n].getName().equals(dol[m].getName()))
{
sum += dol[m].getChange();
dol[m].setName(""); // Set name to empty to mark as processed
}
}
if (!dol[n].getName().equals("")) {
System.out.printf("%s -- %d\n", dol[n].getName(), sum);
}
}
}
public static void main(String[] args)
{
// Test with 5 records
Dollars[] dollarsArr = new Dollars[5];
dollarsArr[0] = new Dollars("john", 10);
dollarsArr[1] = new Dollars("peter", 12);
dollarsArr[2] = new Dollars("sam", 5);
dollarsArr[3] = new Dollars("alvin", 16);
dollarsArr[4] = new Dollars("peter", 30);
displayArray(dollarsArr);
}
}
英文:
I am learning java and I hit into a snag as I could not figure out my loop or array.
I have an array which contains class objects containing a string and integer parameters, in my code, it will be name and dollars.
I am trying to print out the array in which, if there is a same name, it is to print once and with the sum of the dollars (from the same name).
In my Dollars.java
public class Dollars
{
private String name;
private int dollars;
public dollars (String name, int dollars)
{
this.name = name;
this.dollars = dollars;
}
public String getName()
{
return name;
}
public int getChange()
{
return dollars;
}
}
In my main file/ TestDollars.java
public class TestDollars
{
public static void displayArray(Dollars[] dol)
{
int sum = 0;
for (int n=0; n<dol.length; n++)
{
for (int m=n+1; m<dol.length; m++)
{
if (dol[n].getName().equals(dol[m].getName()))
{
// System.out.printf("%s -- %d\n", dol[n].getName(), dol[n].getChange());
sum = dol[n].getChange() + dol[m].getChange();
System.out.printf("%s -- %d\n", dol[m].getName(), sum);
break;
}
}
System.out.printf("%s -- %d\n", dol[n].getName(), dol[n].getChange());
}
}
public static void main(String[] args)
{
// Test with 5 records
Dollars[] dollarsArr = new Dollars[5];
dollarsArr[0] = new Dollars("john", 10);
dollarsArr[1] = new Dollars("peter", 12);
dollarsArr[2] = new Dollars("sam", 5);
dollarsArr[3] = new Dollars("alvin", 16);
dollarsArr[4] = new Dollars("peter", 30);
displayArray(dollarsArr);
}
}
Irregardless where I place my print statement in the displayArray
, the record 'peter' will gets printed twice.
Expected output:
john -- 10
peter -- 42
sam -- 5
alvin -- 16
Current output:
john -- 10
peter -- 42
peter -- 12
sam -- 5
alvin -- 16
peter -- 30
答案1
得分: 4
你想按名称对列表进行分组,请使用JAVA 8+ API Stream和收集器group by
public static void displayArray(Dollars[] dol) {
Stream.of(dol)
// 按名称分组
.collect(Collectors.groupingBy(Dollars::getName))
.entrySet().stream()
// 收集名称和计算总和的映射
.collect(Collectors.toMap(x -> {
int total = x.getValue().stream().mapToInt(Dollars::getChange).sum();
return new Dollars(x.getKey(), total);
}, Map.Entry::getValue))
// 打印
.forEach((dollarsTotal, vals) -> {
System.out.println(dollarsTotal.getName() + " -- " + dollarsTotal.getChange());
// 奖励:显示交易:
for (Dollars transaction : vals) {
System.out.println(" \t " + transaction.getName() + " add -- " + transaction.getChange());
}
});
}
如果你只想要值,可以收集键集合
Set<Dollars> groupedByName = Stream.of(dol)
// 按名称分组
.collect(Collectors.groupingBy(Dollars::getName))
.entrySet().stream()
// 收集名称和计算总和的映射
.collect(Collectors.toMap(x -> {
int total = x.getValue().stream().mapToInt(Dollars::getChange).sum();
return new Dollars(x.getKey(), total);
}, Map.Entry::getValue)).keySet();
英文:
You want to group your list by name, please use JAVA 8+ API Stream and the collector group by
public static void displayArray(Dollars[] dol)
{
Stream.of(dol)
// Group by name
.collect(Collectors.groupingBy(Dollars::getName))
.entrySet().stream()
// Collect a map name and calculate the sum
.collect(
Collectors.toMap(x -> {
int total= x.getValue().stream().mapToInt(Dollars::getChange).sum();
return new Dollars(x.getKey(),total);
}, Map.Entry::getValue))
// Print
.forEach((dollarsTotal, vals) -> {
System.out.println(dollarsTotal.getName()+ " -- "+ dollarsTotal.getChange());
// Bonus : Display transactions :
for(Dollars transaction : vals)
{
System.out.println(" \t "+transaction.getName() + " add -- " + transaction.getChange());
}
});
}
If you want only the values you can collect the keyset
Set<Dollars> groupedByName = Stream.of(dol)
// Group by name
.collect(Collectors.groupingBy(Dollars::getName))
.entrySet().stream()
// Collect a map name and calculate the sum
.collect(
Collectors.toMap(x -> {
int total= x.getValue().stream().mapToInt(Dollars::getChange).sum();
return new Dollars(x.getKey(),total);
}, Map.Entry::getValue)).keySet();
答案2
得分: 3
其他答案指导您修复了您的代码(但它们需要更多的工作来避免重复计算)。
您可以通过使用数据结构(比如映射)来聚合结果,将时间复杂度从 O(n2) 降低到 O(n)
(同时使代码更简洁)。
让我们创建一个 Map<String, Integer>
来将姓名映射到该姓名的总金额。
Map<String, Integer> result = new HashMap<>();
for (int i = 0; i < dol.length; i++) {
if (!result.containsKey(dol[i].getName())) { // 第一次遇到姓名
result.put(dol[i].getName(), dol[i].getChange());
} else {
// 将当前变化值添加到已有的总和中
int sumSoFar = result.get(dol[i].getName());
result.put(dol[i].getName(), sumSoFar + dol[i].getChange());
}
}
System.out.println(result);
结果为:
{peter=42, alvin=16, john=10, sam=5}
您可以使用 Map
的 merge
方法简化上述代码,如下所示:
for (Dollars dollars : dol) {
result.merge(dollars.getName(), dollars.getChange(), Integer::sum);
}
第三个参数是一个 BiFunction
,它将旧值和新值相加(迄今累积的总和和当前变化值)。当作为 lambda 表达式编写时,Integer::sum
可以写成 (sumSoFar, currentChange) -> sumSoFar + currentChange
。
使用流式编程的方式是使用 Collectors.groupingBy
和 Collectors.summingInt
。
Arrays.stream(dol)
.collect(Collectors.groupingBy(Dollars::getName, Collectors.summingInt(Dollars::getChange)));
英文:
The other answer guides you on fixing your code (Buy they require more work to avoid double counting).
You can reduce the time complexity from O(n<sup>2</sup>) to O(n)
(and make it simpler) by having a data structure (like a map) to aggregate the result.
Let us create a Map<String, Integer>
to map a name to the total dollars for that name.
Map<String, Integer> result = new HashMap<>();
for (int i = 0; i < dol.length; i++) {
if (!result.containsKey(dol[i].getName())) { //first time you encounter a name
result.put(dol[i].getName(), dol[i].getChange());
} else {
//add the current change to the already existing sum
int sumSoFar= result.get(dol[i].getName());
result.put(dol[i].getName(), sumSoFar + dol[i].getChange());
}
}
System.out.println(result);
Result is,
{peter=42, alvin=16, john=10, sam=5}
You can simplify the above code using Map's merge
method as:
for (Dollars dollars : dol) {
result.merge(dollars.getName(), dollars.getChange(), Integer::sum);
}
The third argument is a BiFunction
which sums up the old value and new value (the sum accumulated so far and the current change value). When written as a lambda expression, Integer::sum
can be written as (sumSoFar, currentChange) -> sumSoFar + currentChange
.
A stream evangelist way would be to use Collectors.groupingBy
and Collectors.summingInt
.
Arrays.stream(dol)
.collect(Collectors.groupingBy(Dollars::getName, Collectors.summingInt(Dollars::getChange)));
答案3
得分: 1
在遍历数组时,将每个非空数组元素的change
赋值给变量,例如sum
,然后将后续重复元素的change
添加到其中。确保在发现重复元素的索引处赋值为null
,以防止它们再次计数。这也意味着在对数组元素执行任何操作之前,您必须执行null
检查。在完成对重复元素的整个数组的检查后,打印sum
的值。
public static void displayArray(Dollars[] dol) {
for (int n = 0; n < dol.length; n++) {
if (dol[n] != null) {
int sum = dol[n].getChange();
for (int m = n + 1; m < dol.length; m++) {
if (dol[m] != null && dol[n].getName().equals(dol[m].getName())) {
sum += dol[m].getChange();
dol[m] = null;
}
}
System.out.printf("%s -- %d\n", dol[n].getName(), sum);
}
}
}
输出:
john -- 10
peter -- 42
sam -- 5
alvin -- 16
注意: 如果要保持原始数组不变,在方法displayArray
中传递数组的克隆,而不是传递数组本身,如下所示:
displayArray(dollarsArr.clone());
英文:
While navigating the array, assign the change
of each non-null array-element to a variable e.g. sum
and then add the change
of the succeeding duplicate elements to it. Make sure to assign null
to the indices where duplicate elements are found so that they can not be counted again. It also means that you will have to perform a null
check before performing any operation on the array elements. Print the value of sum
once you have checked the complete array for duplicate elements.
public static void displayArray(Dollars[] dol) {
for (int n = 0; n < dol.length; n++) {
if (dol[n] != null) {
int sum = dol[n].getChange();
for (int m = n + 1; m < dol.length; m++) {
if (dol[m] != null && dol[n].getName().equals(dol[m].getName())) {
sum += dol[m].getChange();
dol[m] = null;
}
}
System.out.printf("%s -- %d\n", dol[n].getName(), sum);
}
}
}
Output:
john -- 10
peter -- 42
sam -- 5
alvin -- 16
Note: If you want to keep the original array intact, pass the clone of the array to the method, displayArray
instead of passing the array itself as shown below:
displayArray(dollarsArr.clone());
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论