I have objects which have a parameter name and a parameter counter. Those objects are stores inside a list. Some of the items in my list have the duplicate parameter "name". I want to remove the duplicates inside the list and add the counter of that duplicate to the duplicate-objects parameter.
class Person{
Person({this.name, this.counter)};
String name;
int counter;
}
List<Person> theList = [];
theList.add(Person(name:"Ben", counter: 2);
theList.add(Person(name:"Ben", counter: 5);
//I need a function that changes the List to show Ben with counter 7
class Person{
final String name;
int counter;
Person({required this.name, required this.counter});
}
extension on List<Person> {
void addPerson({required String name, required int counter}) {
if (isNotEmpty) {
try {
var person = firstWhere((p) => p.name == name);
person.counter += counter;
} catch(e) {
add(Person(name:name, counter: counter));
}
} else {
add(Person(name:name, counter: counter));
}
}
}
void main() {
var theList = <Person>[];
theList.addPerson(name:"Lucho", counter: 4);
theList.addPerson(name:"Ben", counter: 2);
theList.addPerson(name:"Ben", counter: 5);
print(theList);
print(theList.length);
print("${theList[1].name} - ${theList[1].counter}");
}
Result:
[Instance of 'Person', Instance of 'Person']
2
Ben - 7
first define a class for a list of Persons:
class PersonList{
List<Person> _personList = [];
get personList{
return [..._personList];
}
void addToList(Person person){
for(int i=0; i<_personList.length; i++){
if(_personList[i].name == person.name){
_personList[i].counter = _personList[i].counter + person.counter;
return;
}
}
_personList.add(person);
return;
}
}
then, you can create a new instance of it and add some entries to the list:
PersonList theList = new PersonList();
theList.addToList(Person(name:"Ben", counter: 2));
print(theList.personList[0].counter);
theList.addToList(Person(name:"Ben", counter: 5));
print(theList.personList[0].counter);
feel free to only use the addToList method.
Related
i have the following list with duplicate values and i need to check if the values is duplicated print it else skip it
List lst = ["AA","BB","BBB","AA"];
what should printed is :
AA
Thanks ;
Would this work for you?
List list = ["AA", "BB", "BBB", "AA"];
List distinctList = list.toSet().toList();
void main() {
for (int i = 0; i < distinctList.length; i++) {
list.remove(distinctList[i]);
}
//// or you could use a "for in" like this:
// for (var item in distinctList) {
// list.remove(item);
// }
print(list.toSet().toList());
}
Or using forEach() on the Set
List list = ['AA', 'BB', 'BBB', 'AA'];
void main() {
list.toSet().forEach((item) => {list.remove(item)});
print(list.toSet().toList());
}
List lst = ["AA","BB","BBB","AA"];
int duplicateDetectedCount = -1;
String duplicateItem = "";
for(String item in lst){
for(String innerItem in lst){
if(item == innerItem){
duplicateDetectedCount++;
if(duplicateDetectedCount == 1){
duplicateItem = innerItem;
}
}
}
}
print(duplicateItem); // prints AA
lst.where((e) => lst.where((element) => element == e).length > 1).toSet().toList();
One Liner
I created a code, for specific task. But, I think: must to have better manner to do this code.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class InnerListContainingItemWithSpecificPropertyValue {
public static void main(String[] args) {
List<List<Person>> nestedPersonList = Arrays.asList(
Arrays.asList(new Person("a0", 0), new Person("b0", 1)), //0
Arrays.asList(new Person("a1", 0), new Person("b1", 1)), //1
Arrays.asList(new Person("a2", 0), new Person("b2", 1)), //2
Arrays.asList(new Person("a3", 0), new Person("b3", 1)) // 5
);
List<List<Person>> outNestedPersonList = new ArrayList<>();
nestedPersonList.stream().flatMap(List::stream).forEach(outerPerson -> {
//Determine if Exist Some inner List
boolean ageFound = outNestedPersonList
.stream()
.flatMap(List::stream)
.filter(innerPerson -> outerPerson.getAge() == innerPerson.getAge())
.count() > 0L;
List<Person> listPersonWithAge;
if (!ageFound) {
listPersonWithAge = new ArrayList<>();
outNestedPersonList.add(listPersonWithAge);
} else {
// Get the Inner List with Specific Property Value
listPersonWithAge = outNestedPersonList
.stream()
.filter(innerListPerson -> {
return innerListPerson
.stream()
.filter(innerPerson -> outerPerson.getAge() == innerPerson.getAge())
.count() > 0L;
}).findFirst().get();
}
listPersonWithAge.add(outerPerson);
// Do something
if (listPersonWithAge.size() == 4) {
System.out.println("listPerson with age:" + outerPerson.getAge() + "\twill be removed!");
outNestedPersonList.remove(listPersonWithAge);
}
});
}
public static class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + Objects.hashCode(this.name);
hash = 73 * hash + this.age;
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Person other = (Person) obj;
if (this.age != other.age) {
return false;
}
if (!Objects.equals(this.name, other.name)) {
return false;
}
return true;
}
#Override
public String toString() {
return "Person{" + "name=" + name + ", age=" + age + '}';
}
}
}
output:
listPerson with age:0 will be removed!
listPerson with age:1 will be removed!
Alternatively my code:
How know if is there inner List containing some item with some
Property Value?
How I can to obtain the inner list with that item?
If the external list does not contain an internal list, How create one?
The first step of improving your code is to avoid using flatMap. It makes it easier to operate on the nested data, but you are trying to operate on one of the sublists, not on the all of the people as a whole.
You are trying to operate on one sublist, not all of the people in all of the lists, so instead of using flatMap, you can nest two sets of stream operations.
listOfListOfPeople.stream()
// filter out sublists that don't have anyone with the target age
.filter(sublist ->
// Check if the nested list contains anyone with the given age
sublist.stream().anyMatch(p -> p.age == targetAge))
// get one sublist out of the stream
.findAny()
// if there wasn't one, get an empty list
.orElse(Collections.emptyList());
If you want to be able to modify the empty list you get if there aren't any people with the target age, replace the last line with something like .orElseGet(ArrayList::new).
I have a text file called highscore.txt and I know the format of the data going into the file which works in the following way:
Username:score
I then need to search through the whole file to see where the new score needs to be added such that the file is in order of score from largest to smallest
List<string> tempoaryList = new List<string>();
List<int> valueList = new List<int>();
string lineValues = "";
using (StreamReader sr = new StreamReader(finalPath))
{
while (sr.EndOfStream == false)
{
lineValues = sr.ReadLine();
tempoaryList.Add(lineValues);
int data = Convert.ToInt32(lineValues.Substring(lineValues.LastIndexOf(':') + 1));
valueList.Add(data);
}
}
valueList.Sort();
for(int i =0; i > valueList.Count; i++)
{
if(valueList[i] <= playerScore)
{
tempoaryList.Insert(i - 1, playerScore.ToString());
}
}
using (StreamWriter sw = new StreamWriter(finalPath, false))
{
for (int i = 0; i < tempoaryList.Count; i++)
{
sw.WriteLine(tempoaryList[i]);
Debug.Log(tempoaryList[i]);
}
}
The above just simply doesn't change the text file and leaves it as it was found, any ideas of what I am doing wrong?
You should change your code to this:
ScoreList.cs
using UnityEngine;
using System;
using System.IO;
using System.Collections.Generic;
public class ScoreList : MonoBehaviour {
private void Start() {
GameOver.GameOverEvent += UpdateScoreBoardFile;
}
private void UpdateScoreBoardFile(string playerName, int playerScore) {
string lineValues;
string finalPath = "[ScoreBoard File Location]";
List<string> tempoaryList = new List<string>();
List<int> valueList = new List<int>();
bool isScoreLowest = true;
using (StreamReader sr = new StreamReader(finalPath)) {
while (sr.EndOfStream == false) {
lineValues = sr.ReadLine();
tempoaryList.Add(lineValues);
int data = Convert.ToInt32(lineValues.Substring(lineValues.LastIndexOf(':') + 1));
valueList.Add(data);
}
}
if (tempoaryList != null) {
for (int i = 0; i < valueList.Count; i++) {
if (valueList[i] <= playerScore) {
tempoaryList.Insert(i, playerName + ":" + playerScore.ToString());
isScoreLowest = false;
break;
}
}
}
if (isScoreLowest) {
tempoaryList.Add(playerName + ":" + playerScore.ToString());
}
using (StreamWriter sw = new StreamWriter(finalPath, false)) {
for (int i = 0; i < tempoaryList.Count; i++) {
sw.WriteLine(tempoaryList[i]);
Debug.Log(tempoaryList[i]);
}
}
}
}
GameOver.cs (or wherever you manage the game over condition):
using UnityEngine;
using System;
public class GameOver : MonoBehaviour {
public static event Action<string, int> GameOverEvent;
string playerName;
int finalScore;
private void GameOver() {
//Do other stuff when the game is over
GameOverEvent(playerName, finalScore);
}
}
Explanation of the changes:
isScoreLowest is needed to Add the new lowest score at the end of the list, since the for loop won't add it by itself.
The if (tempoaryList != null) check is done to skip the for loop when the scoreboard is empty.
And you saved yourself from doing a Sort, which is always a good thing. :)
Duplicate of Count occurrences of words in ArrayList
i trying to counts duplicates of my JSON response.
Im got values from 1,2 ... to 13,14
First what i do is sort the list:
Collections.sort(calues);
every value can be used 4 times.
So at last i have list with 1,1,1,1,2,2,2,2.....14,14,14,14
I need to count repeated values and when any value like 1,2 etc will be repeated 3 times i need to give message to user.
How i can do this?
Thanks for help :)
Going with tutorial i create this:
public int count(List<Integer> nums) {
boolean inclump = false;
int clumpcnt = 0;
for (int i = 1; i < nums.size(); i++) {
if (Objects.equals(nums.get(i), nums.get(i - 1))) {
if (!inclump) {
inclump = true;
clumpcnt++;
if(clumpcnt ==3){
Utils.showToast(getApplicationContext(), "WOW VALUE REPEATED 3 TIMES, YOU WIN");
}
}
} else {
inclump = false;
}
}
return clumpcnt;
}
but this count the values and when values like 2,2 and 3,3 and 4,4 then this function enter
if(clumpcnt ==3){
Utils.showToast(getApplicationContext(), "WOW VALUE REPEATED 3 TIMES, YOU WIN");
}
I declared a list private List<Integer> cardsValues = new ArrayList<>();
Then i added values here:
first 5 on start application:
#Override
public void onNext(#NonNull Cards cards) {
cardsArray = cards.getArrayCards();
for (Card item : cardsArray) {
imgUrls.add(item.getImage());
cardsValues.add(item.getRank());
}
}
And the on every click with "Get new Cards"
Im adding new value with this same method
for (Card item : cardsArray) {
imgUrls.add(item.getImage());
cardsValues.add(item.getRank());
}
And here i call the method
private void checkDuplicateAchievement() {
Collections.sort(cardsValues);
count(cardsValues);
}
Here is my full method
private void getCards(final String deck_id, final int count) {
cardApi.getCards(deck_id, count)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Cards>() {
#Override
public void onSubscribe(#NonNull Disposable d) {
}
#Override
public void onNext(#NonNull Cards cards) {
cardsArray = cards.getArrayCards();
for (Card item : cardsArray) {
imgUrls.add(item.getImage());
cardsValues.add(item.getRank());
}
cardsRecyclerView.notifyDataSetChanged(); recyclerView.smoothScrollToPosition(cardsRecyclerView.getItemCount());
checkDuplicateAchievement();
}
#Override
public void onError(#NonNull Throwable e) {
}
#Override
public void onComplete() {
}
});
}
You can make use of a HashMap like below.
** Not tested , typing java after a long time!, Just to give you an idea.
public int count(List<Integer> nums) {
Map<Integer, Integer> countMap = new HashMap<Integer, Integer>();
for (int i = 1; i < nums.size(); i++) {
if(countMap.get(nums[i]) != null){
countMap.set(i, countMap.get(nums[i]) + 1)
if (countMap.get(i) >=3){
Utils.showToast(getApplicationContext(), "WOW VALUE REPEATED 3 TIMES, YOU WIN");
}
}else{
countMap.set(i, 1)
}
}
}
Try this:
public int count(List<Integer> nums) {
boolean inclump = false; // Not used
int clumpcnt = 0;
int value = nums.get(0);
for (int i = 1; i < nums.size(); i++) {
if (Objects.equals(value, nums.get(i))) {
clumpcnt++;
if (clumpcnt == 3) {
Utils.showToast(getApplicationContext(), "WOW VALUE REPEATED 3 TIMES, YOU WIN");
Log.d("COUNT", "WOW VALUE " + String.valueOf(value) + " REPEATED 3 TIMES, YOU WIN");
clumpcnt = 0;
}
} else {
clumpcnt = 0;
value = nums.get(i);
}
}
return clumpcnt;
}
FYI, nums list contains 1,1,1,1,2,2,2,2,3,3,3,3
OUTPUT LOG:
28078-28078/com.ferdous.stackoverflowanswer D/COUNT: WOW VALUE 1 REPEATED 3 TIMES, YOU WIN
28078-28078/com.ferdous.stackoverflowanswer D/COUNT: WOW VALUE 2 REPEATED 3 TIMES, YOU WIN
28078-28078/com.ferdous.stackoverflowanswer D/COUNT: WOW VALUE 3 REPEATED 3 TIMES, YOU WIN
You can sort your list and then loop the sorted elements and compare values at adjacent positions.If they match then duplicates are present
I am trying to add two items into my QListWidget dynamically. However, the following codes only allow me to add only the last item into the list. strList.size() contains 4 items. Assuming name contains "ABC 1" and "ABC 2".
Is my loop incorrect? Or is my method of adding items into the listWidget wrong?
.h:
public:
QListWidgetItem *item[2];
.cpp:
...
while(!xml.atEnd())
{
xml.readNextStartElement();
if(xml.isStartElement())
{
if(xml.name() == "OS")
{
strList << xml.readElementText();
}
}
}
int num = 0;
for(int i = 0; i < strList.size(); i++)
{
if(strList[i] == "ABC")
{
QString name = strList[i] + strList[i+1];
item[num] = new QListWidgetItem();
item[num]->setText(name);
ui.listWidget->insertItem(num, item[num]);
num += 1;
}
}
Output (listWidget):
ABC02
Expected output (listWidget):
ABC01 ABC02