需要帮助了解为啥要从我的所有列表中删除数据

Posted

技术标签:

【中文标题】需要帮助了解为啥要从我的所有列表中删除数据【英文标题】:Need help understanding why data is being removed from all my lists需要帮助了解为什么要从我的所有列表中删除数据 【发布时间】:2020-11-21 09:10:45 【问题描述】:

我目前有问题和答案从 .json 文件加载到统一中,然后将此数据放置在未回答的问题列表中,然后当生成新问题时,它会删除当前显示的问题。但是,它也会删除加载信息的数据主列表。下面的代码就是用来做这个的:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.IO;
    using UnityEngine.UI;
    
    public class QuestionHandler : MonoBehaviour
    
        [SerializeField] public Text questionText;
        [SerializeField] public Text answerAText;
        [SerializeField] public Text answerBText;
        [SerializeField] public Text answerCText;
    
        [SerializeField]
        private QuestionData _QuestionData = new QuestionData();
        public static List<Question> unansweredQuestions;
        private Question currentQuestion;
        private QuestionData questionData;
    
        public void SaveIntoJson()
        
            string question = JsonUtility.ToJson(_QuestionData, true);
            System.IO.File.WriteAllText(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData/QuestionData.json", question);
            Debug.Log(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData/QuestionData.json");
        
    
        // Start is called before the first frame update
        void Start()
        
            if(!Directory.Exists(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData"))
            
                Directory.CreateDirectory(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData");
                File.Create(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData/QuestionData.json");
                SaveIntoJson();
            
            Load();
            Debug.Log(_QuestionData.questions[0].questionName);
    
            //if the unansweredQuestion list has no data or all the questions have been removed it will copy in the data from the _QuestionData list
            if (unansweredQuestions == null || unansweredQuestions.Count == 0)
            
                Debug.Log("No questions present loading in saved data");
                unansweredQuestions = _QuestionData.questions;
            
            Debug.Log(unansweredQuestions[0].questionName);
    
            SetCurrentQuestion();
        
    
        // Update is called once per frame
        void Update()
        
            
        
        public void SetCurrentQuestion()
        
            int randomQuestionIndex = Random.Range(0, unansweredQuestions.Count);
            currentQuestion = unansweredQuestions[randomQuestionIndex];
    
            questionText.text = currentQuestion.questionName;
            answerAText.text = currentQuestion.answerA;
            answerBText.text = currentQuestion.answerB;
            answerCText.text = currentQuestion.answerC;
        
    
        public void SetNewCurrentQuestion()
        
            if (unansweredQuestions == null || unansweredQuestions.Count <= 0)
            
                Debug.Log("No more questions left in the list!");
                _QuestionData = questionData;
            
            else
            
                //removes current question from the list so no question comes up twice
                unansweredQuestions.Remove(currentQuestion);
    
                //randomly picks a new question out the remaining questions
                int randomQuestionIndex = Random.Range(0, unansweredQuestions.Count);
                currentQuestion = unansweredQuestions[randomQuestionIndex];
    
                questionText.text = currentQuestion.questionName;
                answerAText.text = currentQuestion.answerA;
                answerBText.text = currentQuestion.answerB;
                answerCText.text = currentQuestion.answerC;
    
                Debug.Log(_QuestionData.questions.Count);
                Debug.Log(unansweredQuestions.Count);
                    
        
    
        void Load()
        
            string filePath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData/QuestionData.json");
            string data = System.IO.File.ReadAllText(filePath);
    
            questionData = JsonUtility.FromJson<QuestionData>(data);
            Debug.Log("Got Data!");
            //sets the loaded questiondata into the game question list
            _QuestionData = questionData;
        
    
        private void OnApplicationQuit()
        
            //SaveIntoJson();
        
    
    
    //format of the questions within the game
    [System.Serializable]
    public class QuestionData
    
        public List<Question> questions = new List<Question>();
    
    
    [System.Serializable]
    public class Question
    
        public string questionName;
        public string answerA;
        public bool isA;
        public string answerB;
        public bool isB;
        public string answerC;
        public bool isC;
    

在左侧显示问题数据的主统一屏幕:

任何理解这一点的帮助都会很棒我已经尝试使用debug.log 来查看发生了什么,但我无法解决。

【问题讨论】:

【参考方案1】:

你在做

unansweredQuestions = _QuestionData.questions;

所以在这一行之后,两个字段都指向同一个列表引用。 =>当您稍后通过

删除问题时
unansweredQuestions.Remove(currentQuestion);

此项目已从 _QuestionData.questions 中删除,因为它是同一个列表


为了避免您应该创建和处理列表的副本,而不是像

unansweredQuestions = new List<Question>(_QuestionData.questions);

那么为了节省你可能只想保留unansweredQuestions,除了第一次

public void SaveIntoJson(bool overwriteWithUnanswered = true)

    if(overwriteWithUnanswered) _QuestionData.questions = unansweredQuestions;

    var question = JsonUtility.ToJson(_QuestionData, true);
    System.IO.File.WriteAllText(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData/QuestionData.json", question);
    Debug.Log(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData/QuestionData.json");

并且只在`Start中第一次传入false

if(!Directory.Exists(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData"))

    Directory.CreateDirectory(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData");
    File.Create(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + "/QuestionGameData/QuestionData.json");
    SaveIntoJson(false);


另外两个注意事项:

通常对于文件路径,您应该始终使用 Path.Combine 而不是手动连接 + "/"

您应该存储路径一次,而不是一直一次又一次地获取它

  private readonly string filePath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop), "QuestionGameData", "QuestionData.json");

然后简单地在任何地方重复使用它,例如在

public void SaveIntoJson(bool overwriteWithUnanswered = true)

    if(overwriteWithUnanswered) _QuestionData.questions = unansweredQuestions;

    var question = JsonUtility.ToJson(_QuestionData, true);
    Debug.Log(filePath);
    System.IO.File.WriteAllText(filePath, questions);    

【讨论】:

【参考方案2】:

因为它是参考副本。创建一个新列表

        //sets the loaded questiondata into the game question list
        _QuestionData.questions  = new List<Question>(questionData);


List<Question> mainlist = new List<Question>();
    List<Question> sublist = new List<Question>();
    Question current;
    [System.Serializable]
    public class Question
    
        public string questionName;
        public string answerA;
        public bool isA;
        public string answerB;
        public bool isB;
        public string answerC;
        public bool isC;
        public override string ToString()
        
            return $"Question  questionName = Answer answerA ";
        
    

    public void Load() 
        mainlist = new List<Question>() 
        
            new Question()questionName="Question A",answerA="A" ,
             new Question()questionName="Question B",answerA="B" ,
              new Question()questionName="Question C",answerA="C" ,
               new Question()questionName="Question D",answerA="D" ,

        ;

        // sublist = mainlist; if you uncommment these you will get the same behavior you have.
        sublist = new List<Question>(mainlist); ///Do these in order to avoid reference problems
    
    public void showList(List<Question> sublist)
    

        foreach (var item in sublist)
        
            Console.WriteLine(item);
        
    
    public void showList()
    

        showList(mainlist);
        showList(sublist);
    
    public void SetCurrentQuestion()
    
        int randomQuestionIndex = new Random().Next(0, mainlist.Count);
        current = mainlist[randomQuestionIndex];

    
    public void Remove()
    
        sublist.Remove(current);
    
    


    static void Main(string[] args)
    
        var p = new Program();
        p.Load();
        p.SetCurrentQuestion();
        p.Remove();
        p.showList();
        Console.WriteLine("Hello World!");
    

【讨论】:

以上是关于需要帮助了解为啥要从我的所有列表中删除数据的主要内容,如果未能解决你的问题,请参考以下文章

Cocoapod:为啥 Xcode 构建过程试图找到已经从我的项目中删除的库

更新 JComboBox

我应该在发布之前从我的代码中删除 e.printStackTrace()

当我所做的只是一个列表时,为啥 Hibernate 会删除我的集合条目?

为啥我不能从我的 UICollectionView 中删除图像?

要从gitlab repo中删除最新的提交,并删除旧的本地提交